Visual Studio .NET 中从类变量生成属性的插件






2.89/5 (9投票s)
用于自动生成属性(Getter 和 Setter)的 Visual Studio 2008 插件。
引言
在 Visual Studio (VS) 中,您必须逐个手动输入或生成属性。 如果您有很多变量,这将非常繁琐。 此属性生成器管理属性的创建和修改。 因此,如果您有十个变量,并使用代码片段,则您必须调用它十次。 使用属性生成器,您可以在一次操作中生成所有您选择的变量。
背景
在本文中,我假设您了解开发插件的基础知识。 如果您不了解这些基础知识,可以阅读 这篇文章。
Using the Code
要使用,*.AddIn 和 *.dll 必须存在于 My Documents\Visual Studio 2008\Addins 中
- ClassField.cs 是一个小类,用于包含关于变量和该变量属性的信息。
- ClassManager.cs 用于检索类、变量和编写属性。
ClassStruct
包含接口Istruct
,此接口封装了CodeClass
和CodeStruct
。CodeClass
是一个 VS 对象,包含有关Class
的信息,而CodeStruct
则包含有关Struct
的信息。
ClassManager
这个类的构造函数接受一个 DTE2
,它是 Visual Studio 的一个对象。 有了此对象,我们可以在活动文档中检索所有代码元素 (Namespace
, Class
, ...)。 为此,我们使用两种方法,ProcessElement
和 LoadClass
。
ProcessElement(CodeElement elem)
是一种递归方法,用于查找活动文档中存在的 Class
或 Struct
。 我们可以使用此属性 kind 知道元素的类型。 找到的 Class
或 Struct
被存储在 m_Classes
中。 它用于将 combobox
与所有类名绑定。 当 combobox
更改时,我们调用方法 LoadClass(IStruct mclass)
。
LoadClass(Istruct mclass)
检索 mclass
及其基类中存在的变量和属性。 此方法返回一个 ClassField
列表,用于创建 treeview
。
private bool LoadClasses()
{
m_Classes = new List<IStruct>();
if (((this.m_applicationObject.ActiveDocument == null) ||
(this.m_applicationObject.ActiveDocument.ProjectItem == null)) ||
((this.m_applicationObject.ActiveDocument.ProjectItem.FileCodeModel == null) ||
(this.m_applicationObject.ActiveDocument.ProjectItem.FileCodeModel.CodeElements
== null)))
{
return false;
}
else
{
foreach (CodeElement element in
this.m_applicationObject.ActiveDocument.ProjectItem.FileCodeModel.CodeElements)
{
this.ProcessElement(element);
}
}
return true;
}
/// <summary>
/// Retrieve all 'class' and 'struct' in the active document
/// </summary>
/// <param name="elem"></param>
/// <param name="rootName"></param>
private void ProcessElement(CodeElement elem)
{
if (elem.Kind == vsCMElement.vsCMElementNamespace)
{
CodeNamespace namespac = elem as CodeNamespace;
foreach (CodeElement element in namespac.Members)
{
this.ProcessElement(element);
}
}
else if (elem.Kind == vsCMElement.vsCMElementClass)
{
ClassStructure item = new ClassStructure(elem as CodeClass);
this.m_Classes.Add(item);
foreach (CodeElement element2 in item.Members)
{
this.ProcessElement(element2);
}
}
else if (elem.Kind == vsCMElement.vsCMElementStruct)
{
StructStructure struct3 = new StructStructure(elem as CodeStruct);
this.m_Classes.Add(struct3);
}
}
为了编写或删除属性,我们使用 EditPoint
,这是一个用于操作文本的 VS 对象。 但是,在此之前,如果属性不存在,我们使用 m_currentStructure.AddProperty
创建它。 m_currentStructure
是当前的 Istruct
。 AddProperty
方法创建一个新的属性代码结构并将代码插入到正确的位置。 对于位置,如果它是 CodeElement
,则在它之后创建属性,0
在开始处创建新元素,而 -1
在末尾创建新元素。 但是此属性是空的,我们检索属性的起始点 (get
或 set
) 和结束点,并删除此选择 point.Delete(point2);
在删除空属性之后,我们编写我们的属性 point.Insert(field.GetMethod)
。 如果属性已经存在,我们插入一个新行并编写我们想要的属性 (get
或 set
)。
要删除属性,我们选择属性的起始点和结束点,之后我们删除选择
public void WriteProperty(ClassField field, bool createGet,
bool createSet,bool setIsInternal, object position)
{
CodeProperty property;
//if null, create a new property else modify
if (field.Property == null)
{
property = this.m_currentStructure.AddProperty
(field, createGet, createSet, position);
//Create summary
EditPoint pt = property.StartPoint.CreateEditPoint();
pt.LineUp(1);
pt.Insert(string.Format(@"
/// <summary>
/// {0}{1}{2}
/// </summary>",
createGet ? "Gets" : string.Empty,
createSet && createGet ? "/" : string.Empty,
createSet ? "Sets" : string.Empty));
if (createGet)
{
property.Getter.IsShared = field.Field.IsShared;
EditPoint point = property.Getter.StartPoint.CreateEditPoint();
EditPoint point2 = property.Getter.EndPoint.CreateEditPoint();
point.Delete(point2);
point.Insert(field.GetMethod);
}
if (createSet)
{
property.Setter.IsShared = field.Field.IsShared;
EditPoint point = property.Setter.StartPoint.CreateEditPoint();
EditPoint point2 = property.Setter.EndPoint.CreateEditPoint();
point.Delete(point2);
point.Insert(field.SetMethod(setIsInternal));
}
}
else
{
property = field.Property;
if (createGet)
{
EditPoint point = property.Getter.EndPoint.CreateEditPoint();
point.Insert(Environment.NewLine);
point.Insert(field.GetMethod);
EditPoint point2 = property.StartPoint.CreateEditPoint();
EditPoint point3 = property.EndPoint.CreateEditPoint();
point2.SmartFormat(point3);
}
if (createSet)
{
EditPoint point = property.Getter.EndPoint.CreateEditPoint();
point.Insert(Environment.NewLine);
point.Insert(field.SetMethod(setIsInternal) );
EditPoint point2 = property.StartPoint.CreateEditPoint();
EditPoint point3 = property.EndPoint.CreateEditPoint();
point2.SmartFormat(point3);
}
}
}
class ClassField
{
public string GetMethod
{
get
{
return string.Format("get {{ return {0}{1}; }}",
this.m_Field.IsShared ? "" : "this.", this.m_Field.Name);
}
}
public string SetMethod(bool isInternal)
{
return string.Format("{2} set {{ {0}{1} = value; }}",
this.m_Field.IsShared ? "" : "this.", this.m_Field.Name, isInternal ?
"internal" : string.Empty );
}
}
历史
- 2009 年 12 月 22 日 - 版本 1.0