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

发布于 2024-12-29 08:23:14 字数 740 浏览 2 评论 0原文

这是一个关于我如何避免标记界面的示例。

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

Here is an example abot how I'm avoiding marker interfaces.

public class AssignableAttribute : Attribute { }

[Assignable]  
public class Foo   
{      
   ...  
}  

[Assignable]  
public class Bar
{      
   ...  
}  

And I'm try to add it to a dictionary Why can't I code a dictionary like this and how to fix it?

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

Avoid using marker interfaces (interfaces with no members).

Custom attributes provide a way to mark a type. For more information
about custom attributes, see Writing Custom Attributes. Custom
attributes are preferred when you can defer checking for the attribute
until the code is executing. If your scenario requires compile-time
checking, you cannot comply with this guideline.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

是伱的 2025-01-05 08:23:14

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

这就是关键。当您尝试使用这样的泛型时,您正在使用编译时检查。您可以推迟使用Dictionary进行运行时检查,但我认为如果没有某些特殊情况,没有人会更喜欢这样做 - 这是额外的努力,而且潜在的错误没有任何实际的好处。

请记住,指南只是建议,不必遵循。这个特定的指南甚至告诉您不应该遵循它的情况,这正是您当前所处的情况。

Custom attributes are preferred when you can defer checking for the attribute until the code is executing. If your scenario requires compile-time checking, you cannot comply with this guideline.

That's the key. When you try to use a generic like that, you're using compile-time checking. You could defer to run-time checking with a Dictionary<string, Object>, but I don't think anyone would prefer that without some special circumstance - it's extra effort and potential for bugs without any real benefit.

Remember, guidelines are only suggestions, and do not have to be followed. This particular guideline even tells you the case where you should not follow it, the very case you are currently in.

苦笑流年记忆 2025-01-05 08:23:14

类型与属性无关。

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

The type has nothing to do with attributes.

You should use an interface called IFoo, e.g.

 interface IFoo 
 {
     // various methods
 }

 public class Foo : IFoo
 {
 }

 public class Bar : IFoo { }

And the dictionary

 Dictionary<string, IFoo> dictionary = new ...();
 dictionary.Add("foo", new Foo());
 dictionary.Add("bar", new Bar());
诗笺 2025-01-05 08:23:14

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

If you don't want to use an interface you can make a dictionary of objects and just check if the type has the AssignableAttribute specified before adding it to your dictionary

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);
}
半岛未凉 2025-01-05 08:23:14

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

编辑我有点不清楚Assignable属性的作用,我认为它是某种转换或反序列化?

怎么样:将 Assignable 属性设置为通用接口 IAssignableFrom

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());
  }
}

Sounds like you are not using the framework available to you to the fullest. The solution to not having marker interfaces is to have an interface that is not a marker.

EDIT I am a bit unclear as to Assignable attribute does, I assume it's some sort of a conversion or deserialization?

How about this: make Assignable attribute into a generic interface 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());
  }
}
永不分离 2025-01-05 08:23:14

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

编辑

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

You cannot express something like "A dictionary of types which have a certain attribute assigned". A type provides you with operations you can invoke on it. By putting an attribute on a type you do not add any operations to it - you basically just provide some additional meta data. If you want to avoid marker interfaces you need to elaborate a bit on what problem exactly you are trying to solve with this.

Edit

Attributes do not change the way a type behaves (they do not add additional operations nor do they change the implementation of the type). They are completely orthogonal to your class hierarchy. They are mainly used so some framework can infer some additional meaning at runtime about a type or it's members (for example the xml serialzier can be told via attribute in which ways to serialize certina members or to ignore certain members). You can't use attributes as compile type restrictions for generics in the sense that you allow all types having a certain attribute attached (the compiler can't check that basically).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文