Warm tip: This article is reproduced from serverfault.com, please click

wpf-是否可以使用 EnvDTE.ClassInfo 对象测试接口实现

(wpf - Is it possible to test for an interface implementation using EnvDTE.ClassInfo objects)

发布于 2013-04-16 21:26:54

全部,

我有一个 T4 模板,它生成样板代码,用于处理我的属性更改通知,并根据我分配给类的属性自动为我注册依赖属性。我使用 EnvDTE 在项目中上下移动并检索 ClassInfo 对象的 IEnumerable 来完成此操作。然后我通过 ClassInfo.Attributes 枚举以检索具有我创建的某些自定义属性(即 INotifyPropertyChangedAttributeAttribute:System.Attribute)的 ClassInfo 对象,以及我需要让模板为我编写样板代码的所有相关信息。

现在,我的问题是,是否可以(使用 EnvDTE)检查可能从基类继承的接口实现(例如 INotifyPropertyChanged),这样我的类中就不会出现两个 PropertyChanged 事件(一个在继承的类和代码生成的部分类中的一个)?

例如:

public class vmBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null) PropertyChanged(this, e);
    }
}

[INotifyPropertyChangedAttribute(Test1, typeof(string))] //NOTE: By including this attribute, T4 template will automatically generate properties.  What I need to know, though, is if the EnvDTE.ClassInfo can show Internface implementations as well so that I don't recreate the INotifyPropertyChanged Event
public partial class vm: vmBase //Implements INotifyPropertyChanged
{
    //....
}

[INotifyPropertyChangedAttribute(Test2, typeof(string))]
public partial class SomeClassThatDoesNotImplementInotifyPropertyChangedAlready
{
    //....
}

希望这是有道理的。

有关使用 envDTE 和 T4 处理依赖属性注册的示例,请参见http://www.scottlogic.co.uk/blog/colin/2009/08/declarative-dependency-property-definition-with-t4-dte/我的项目中的概念是相同的,只是我正在调整它以处理 INotifyPropertyChanged 样板代码。

提前致谢。

Questioner
William
Viewed
0
Nico 2013-04-17 06:47:02

我花了一点时间,但是是的 - 有一种方法可以通过 EnvDTE 找出给定的类是否以某种方式继承了给定的接口。

此代码片段仅检测直接从实现 INotifyPropertyChanged 的​​另一个类继承的类。所以在使用它之前,我们会在这里添加一些递归逻辑......

<#
// get a reference to the project of this t4 template
var project = VisualStudioHelper.CurrentProject;
// get all class items from the code model
var allClasses = VisualStudioHelper.GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false);

// iterate all classes
foreach(EnvDTE.CodeClass codeClass in allClasses)
{
    // get all interfaces implemented by this class

    var allInterfaces = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.ImplementedInterfaces, EnvDTE.vsCMElement.vsCMElementInterface, true);
    if (allInterfaces.OfType<EnvDTE.CodeInterface>()
                     .Any(i => i.Name == "INotifyPropertyChanged"))
    {
        #>Implements Interface Directly: <#= codeClass.FullName #>
        <#

        // find classes that derive from this code class
        foreach(EnvDTE.CodeClass potentialDerivingClass in allClasses)
        {
            IEnumerable<string> theBases = VisualStudioHelper.GetAllCodeElementsOfType(potentialDerivingClass.Bases, EnvDTE.vsCMElement.vsCMElementClass, true).OfType<EnvDTE.CodeClass>().Select(cc => cc.FullName);
            if (theBases.Any(b => b == codeClass.FullName))
            {
                #>Derives from implementing class: <#= potentialDerivingClass.FullName #>
                <#
            }
        }
    }
}
#>

因此,假设实现 INotifyProperty 的类 A 发生了变化,从 A 派生的类 B 和从 B 派生的另一个类 C,此代码将提出实现 INotifyPropertyChanged 的​​类 A 和 B。

注意:因为使用 EnvDTE 类不是很好,所以我使用了一个名为“tangible Visual Studio Automation Helper”的 tangible T4 Editor 的免费模板库中的可重用模板 - 这使它更容易使用!