Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过C#属性向接口/类添加功能?_C#_Attributes_Custom Attributes - Fatal编程技术网

通过C#属性向接口/类添加功能?

通过C#属性向接口/类添加功能?,c#,attributes,custom-attributes,C#,Attributes,Custom Attributes,我很难用谷歌查询的形式来总结我的问题(可能我的foo关闭了): 我试图通过不编辑类型定义本身,而是通过用接口修饰对象来为接口或类提供一些功能。我尝试的一个简单示例是附加一个名为[Notify]的属性,该属性定义了一个属性更改事件,理想情况下,为接口/类提供事件的使用。我在这方面一直不成功,因此我将向任何可能的设备开放(如果有的话),以实现同等效果: [Notify] public interface IPerson { string Name { get; set; } } [

我很难用谷歌查询的形式来总结我的问题(可能我的foo关闭了):

我试图通过不编辑类型定义本身,而是通过用接口修饰对象来为接口或类提供一些功能。我尝试的一个简单示例是附加一个名为[Notify]的属性,该属性定义了一个属性更改事件,理想情况下,为接口/类提供事件的使用。我在这方面一直不成功,因此我将向任何可能的设备开放(如果有的话),以实现同等效果:

[Notify]
public interface IPerson
{
    string Name { get; set; }
}

    [AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
    public class Notify: Attribute
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

    }
使用IPerson:

IPerson person = PersonFactory.create();
person.PropertyChanged += SomeDelegateHere // the center peice
当然,如果你复制了这段代码,那个人就不会改变财产。无论有无属性,是否有一种方法可以在不更改定义(即不添加接口或基类)的情况下,为IPerson提供更多功能。我知道属性也在变化,但我对元数据方法很满意


提前感谢您提供的任何光线。

属性通常不起任何作用。它们的目的更多的是为它们修饰的类型/字段/属性等提供描述符或元数据

一般的替代方法可能是使用扩展方法,但我认为这在您的情况下也不起作用,因为您正在尝试向类型添加事件


我能想到的唯一可行的替代方法是使用类似PostSharp或其他AOP框架的东西来进行一些代码编织后编译。

您所看到的是挂接方法调用之类的事件,并将一些操作附加到该事件上。这不是C#的默认特性,但可以通过AOP框架完成。PostSharp通过在构建时更改代码(不使用反射)来添加此功能

以下是您需要使用PostSharp实现的内容:

[Serializable]
[IntroduceInterface(typeof(INotifyPropertyChanged), OverrideAction = InterfaceOverrideAction.Ignore)]
[MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict )]
public class NotifyAttribute : InstanceLevelAspect, INotifyPropertyChanged
{        
    [ImportMember("OnPropertyChanged", IsRequired = false)] 
    public Action<string> OnPropertyChangedMethod;    

    [IntroduceMember(Visibility = Visibility.Family, IsVirtual = true, OverrideAction = MemberOverrideAction.Ignore)]
    public void OnPropertyChanged( string propertyName )
    {
        if (PropertyChanged != null )            
            PropertyChanged(Instance, new PropertyChangedEventArgs(propertyName));            
    }

    [IntroduceMember(OverrideAction = MemberOverrideAction.Ignore)]
    public event PropertyChangedEventHandler PropertyChanged;

    [OnLocationSetValueAdvice]
    [MulticastPointcut(Targets = MulticastTargets.Property,  Attributes = MulticastAttributes.Instance)]
    public void OnPropertySet( LocationInterceptionArgs args )
    {            
        if (args.Value == args.GetCurrentValue()) return;

        args.ProceedSetValue();
        this.OnPropertyChangedMethod.Invoke( args.Location.Name );            
    }
}
请记住,实际代码将在编译期间注入程序集中。属性不能添加任何功能。它们只是元数据。在本例中,PostSharp使用元数据生成代码并将其注入程序集

[Notify]
public class Person
{
    public string Name { get; set; }
}