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

时间:2012-01-28 05:34:55

标签: c# interface custom-attributes

这是一个例子,我是如何避免标记接口的。

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

5 个答案:

答案 0 :(得分:3)

  

当您可以推迟检查属性直到代码执行时,首选自定义属性。 如果您的方案需要编译时检查,则无法遵守此准则。

这是关键。当您尝试使用类似的泛型时,您正在使用编译时检查。您可以推迟使用Dictionary<string, Object>进行运行时检查,但我认为如果没有一些特殊情况,我认为没有人愿意这样做 - 这是额外的努力和潜在的错误而没有任何实际好处。

请记住,指南只是建议,不必遵循。此特定指南甚至会告诉您遵循它的情况,即您目前所处的情况。

答案 1 :(得分:0)

您无法表达类似“已分配特定属性的类型字典”之类的内容。类型为您提供可以在其上调用的操作。通过在类型上放置属性,您不会向其添加任何操作 - 您基本上只是提供一些额外的元数据。如果你想避免使用标记接口,你需要详细说明你试图解决的问题。

修改

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

答案 2 :(得分:0)

该类型与属性无关。

您应该使用名为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());

答案 3 :(得分:0)

如果您不想使用界面,您可以创建一个对象字典,只需检查该类型是否在将其添加到您的字典之前指定了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);
}

答案 4 :(得分:0)

听起来你没有充分利用可用的框架。没有标记界面的解决方案是使用而不是标记的界面。

编辑我对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());
  }
}