【问题标题】:Creating new instances for objects in dictionary为字典中的对象创建新实例
【发布时间】:2018-01-02 20:51:19
【问题描述】:

我制作了 Animal 项目并将其设置为 Library。当然在 Animal 项目中我会添加更多的类。在这个项目中,我现在有 2 个类:Dog 和 Method。

//Class Method
public class Method : Attribute{
    public string Name { get; set; }
    public Method(){
        Name = "";
    }
}

//Class Dog
[Method(Name = "dog")]
public class Dog
{
    public int NumberOfLegs { get; set; }
    public string Breed { get; set; }
    public Dog() { }
}

然后我在我的解决方案 Ref 中创建了第二个项目,它是我的主类:

//version 1
class Program{
    public static Dictionary<String, Type> animals;
    static void Main(string[] args){
        Assembly assembly = Assembly.GetEntryAssembly();
        Type[] typ = assembly.GetTypes();
        foreach (Type t in typ){
            animals.Add(t.Name, t);
        }
    }
}

我想实现“狗,狗”,“猫,猫”,“老鼠,老鼠”。其中“dog”是名称属性,而“Dog”是一种类型,因为我可以制作类似

的东西
Activator.CreateInstance(animals[nameAnimal]);

但是现在我做错了,我的方法行不通,我在 .net 核心中找不到解决问题的方法。我只想要属性方法所在的类中的对象。如何实现?

编辑。 我的程序没有看到库“Dog”并搜索“Ref.*”库,例如 Ref、Ref.Program 等。

【问题讨论】:

标签: c# reflection .net-core


【解决方案1】:

您的代码中有很多问题:

  1. 您的代码中有NullReferenceExceptionanimalsnull
  2. 为什么要实现根本不使用的属性?

    您将所有类型存储在程序集assembly.GetTypes(); 中,并且您只想存储定义属性Method 的类型。

    另外,t.Name 不是您的属性的属性,它是 类型的名称Type.Name.

    你可能想要的是:

    var allTypes = assembly.GetTypes();
    
    foreach (var t in allTypes)
    {
        var methodAttribute = t.GetCustomAttribute<Method>();
        if (methodAttribute != null } animals.Add(methodAttribute.Name, t);
    }
    
  3. Method 应该有一个带一个参数的构造函数,你的代码太复杂了:

    public Method(string name)
    {
        Name = name;
    }
    

    并且Name 应该是只读的:

    public string Name { get; }
    
  4. 使用命名约定。属性应该有 Attribute 后缀:

    public class MethodAttribute { ... }
    

    编译器会发挥一些作用,并允许您使用“短”名称:

    [Method("Dog")]
    public class Dog { ... }
    

【讨论】:

  • @nju 这很奇怪。您是否声明了正确的命名空间:using System.Reflection?这应该使CustomAttributeExtensions.cs 提供的扩展方法可用。
  • 在我的项目中 t 是一个 Type 并且不包含这个方法。是的,我有“使用 System.Reflection”
【解决方案2】:

您可以使用以下代码和平..

Assembly assembly = Assembly.GetEntryAssembly();
        Type[] typ = assembly.GetTypes();

        foreach (Type t in typ)
        {
            IList<CustomAttributeData> m = t.GetCustomAttributesData();
            if(m.Count>0)
            animals.Add(t.Name, m[0].NamedArguments[0].TypedValue.Value.ToString());

        }

【讨论】:

  • 'Type' 不包含 'GetCustomAttributesData' 的定义
  • 它包含@nju
  • 对我来说不是。这里 IList m = t.GetCustomAttributesData();我有信息表明“类型”不包含“GetCustomAttributeData”的定义
  • @nju 这是一个扩展方法,你需要 System.Reflection 参考才能让它工作
  • @AntonSemenov 我知道
【解决方案3】:

对不起,我之前的愚蠢。我只是有更多的时间,并再次阅读所有内容。我现在想我明白你的问题了。你想知道的是为什么使用 reelection 你看不到你的其他两个类?原因很简单:这两个类不在同一个程序集中!您的第一个项目编译为 dll。这是它自己的组装。您的第二个项目编译为另一个程序集的 exe。因此,在第二个程序集中使用反射只会向您显示第二个程序集中的类型。

要获得您想要的,只需将您的狗类从库中移出,并将它们包含在您的第二个项目中。然后您将能够在 Main 中看到它们。

编辑

使用这个:

Assembly assembly = Assembly.ReflectionOnlyLoadFrom("yourlibname.dll"); 
Type[] typ = assembly.GetTypes();
foreach (Type t in typ)
{
    animals.Add(t.Name, t);
}

假设您一起编译解决方案,那么 dll 应该与您的 exe 在同一个 bin 文件夹中。否则你需要给出完整的路径。

【讨论】:

  • 是的,这不是一个糟糕的解决方案,但我必须将它保存在不同的项目(库)中。所以我需要搜索这个dll?
  • 程序集不包含 ReflectionOnlyLoadFrom。我正在使用 .net 核心
【解决方案4】:

下面是完整的程序。

class Program
{
    public static Dictionary<String, string> animals = new Dictionary<string, string>();
    static void Main(string[] args)
    {


        Assembly assembly = Assembly.GetEntryAssembly();
        Type[] typ = assembly.GetTypes();

        foreach (Type t in typ)
        {
            IList<CustomAttributeData> m = t.GetCustomAttributesData();
            if(m.Count>0)
            animals.Add(t.Name, m[0].NamedArguments[0].TypedValue.Value.ToString());

        }


    }

}
public class Method : Attribute
{
    public string Name { get; set; }
    public Method()
    {
        Name = "";
    }
}

//Class Dog
[Method(Name = "dog")]
public class Dog
{
    public int NumberOfLegs { get; set; }
    public string Breed { get; set; }
    public Dog() { }
}   

【讨论】:

  • 静线 t.GetCustomAttributesData();错误 - “类型”不包含定义 ....
【解决方案5】:

你可以使用TypeInfoCustomAttributes属性:

class Program
{
    public static Dictionary<string, Type> animals = new Dictionary<string, Type>();

    static void Main(string[] args)
    {
        Assembly assembly = Assembly.GetEntryAssembly();
        Type[] typ = assembly.GetTypes();
        foreach (Type t in typ)
        {
            // check if the type has attribute of Method type
            var attrData = t.GetTypeInfo().CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(Method));
            if(attrData==null || !attrData.NamedArguments.Any(x => string.Equals(x.MemberName, nameof(Method.Name)))) continue;

            animals.Add(attrData.NamedArguments[0].TypedValue.Value.ToString(), t);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多