避免使用字典自定义属性的标记接口

本文关键字:接口 自定义属性 字典 | 更新日期: 2023-09-27 18:21:36

这里有一个关于如何避免标记接口的例子。

public class AssignableAttribute : Attribute { }
[Assignable]  
public class Foo   
{      
   ...  
}  
[Assignable]  
public class Bar
{      
   ...  
}  

我正在尝试将它添加到字典中为什么我不能这样编码字典以及如何修复它?

Dictionary<string, AssignableAttribute> dictionary = new ...();
dictionary.Add("foo", new Foo());
dictionary.Add("bar", new Bar());

避免使用标记接口(没有成员的接口)。

自定义属性提供了一种标记类型的方法。有关详细信息关于自定义属性,请参见编写自定义属性。风俗当您可以推迟检查属性时,首选属性直到代码正在执行。如果您的场景需要编译时间检查,您不能遵守此准则。

http://msdn.microsoft.com/en-us/library/ms229022.aspx

避免使用字典自定义属性的标记接口

当您可以将对属性的检查推迟到代码执行时,首选自定义属性如果您的场景需要编译时检查,则不能遵守此准则

这是关键。当您尝试使用类似的泛型时,您使用的是编译时检查。您可以使用Dictionary<string, Object>进行运行时检查,但我认为在没有特殊情况的情况下,任何人都不会喜欢这样做——这是额外的工作,而且可能会出现错误,没有任何实际好处。

记住,指导方针只是建议,不必遵循。这个特别的指导方针甚至告诉你应该而不是遵循它的情况,也就是你目前所处的情况。

类型与属性无关。

您应该使用一个名为IFoo的接口,例如

 interface IFoo 
 {
     // various methods
 }
 public class Foo : IFoo
 {
 }
 public class Bar : IFoo { }

还有字典

 Dictionary<string, IFoo> dictionary = new ...();
 dictionary.Add("foo", new Foo());
 dictionary.Add("bar", new Bar());

如果你不想使用接口,你可以制作一个对象字典,在将其添加到字典之前,只需检查该类型是否指定了AssignableAttribute

Dictionary<string, object> dictionary = ...;

private void AddAssignable(object assignableObject)
{
     var type = assignableObject.GetType();
     if (type.GetCustomAttributes(typeof(AssignableAttribute), true) == null)
        return;
     dictionary.Add(type.Name, assignableObject);
}

听起来您没有充分使用可用的框架。没有标记接口的解决方案是有一个而不是标记的接口。

EDIT我有点不清楚Assignable属性是什么,我认为这是某种转换还是反序列化?

怎么样:把Assignable属性变成一个通用接口IAssignableFrom<T>

interface IAssignableFrom<T> {
  void AssignFrom(T source);
}
public class Bar : IAssignableFrom<Foo> {
  public void AssignFrom(Foo foo){
     //implementation of assignment here
  }
}
public class Baz : IAssignableFrom<Foo> {
  public void AssignFrom(Foo foo){
     //implementation of assignment here
  }
}
public class Foo : IAssignableFrom<Foo> {
  public void AssignFrom(Foo foo){
     //implementation of assignment here
  }
}
public class Program {
  public static void Main(string[] args){
    IDictionary<string, IAssignableFrom<Foo>> dictionary = new Dictionary<string, IAssignableFrom<Foo>>;
    dictionary.Add("foo", new Foo());
    dictionary.Add("bar", new Bar());
    dictionary.Add("baz", new Baz());
  }
}

您不能表达类似"指定了特定属性的类型字典"的内容。类型为您提供了可以在其上调用的操作。通过在类型上放置属性,您不会向其添加任何操作,基本上只提供了一些额外的元数据。如果你想避免标记接口,你需要详细说明你想用它来解决什么问题。

编辑

属性不会改变类型的行为方式(它们不会添加额外的操作,也不会更改类型的实现)。它们与类层次结构完全正交。它们的主要用途是,一些框架可以在运行时推断出关于类型或其成员的一些额外含义(例如,可以通过属性告知xml serializer序列化certina成员或忽略某些成员的方式)。您不能使用属性作为泛型的编译类型限制,因为您允许所有类型都附加某个属性(编译器基本上无法检查这一点)。