在字典中为对象创建新实例

时间:2017-07-27 08:35:53

标签: c# reflection .net-core

我创建了Animal项目并将其设置为Library。当然在Animal项目中我会添加更多类。在这个项目中,我现在有两个班:狗和方法。

//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”是name属性,而“Dog”是一个类型,这要归功于我能够制作类似

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

但是现在我做错了什么,我的方式不起作用,我无法找到解决我在.net核心问题的解决方案。我只想要来自属性方法的类的对象。怎么实现呢?

修改 我的程序看不到库“Dog”并搜索“Ref。*”库,例如Ref,Ref.Program等。

5 个答案:

答案 0 :(得分:0)

您的代码中存在一些问题:

  1. 您的代码中有一个NullReferenceException; animalsnull
  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. 使用命名约定。属性应具有属性后缀:

    public class MethodAttribute { ... }
    

    编译器会做一些魔术并允许你以任何方式使用“短”名称:

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

答案 1 :(得分:0)

您可以使用以下代码安静..

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

        }

答案 2 :(得分:0)

对不起我早先的愚蠢。我已经有更多的时间再次阅读所有内容。我现在认为我理解你的问题。您想知道的是为什么使用relection您没有看到其他两个类?原因很简单:这两个类不在同一个程序集中!你的第一个项目编译成一个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文件夹中。否则你需要提供完整的路径。

答案 3 :(得分:0)

以下是完整的程序。

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

答案 4 :(得分:0)

您可以使用CustomAttributes的{​​{1}}属性:

TypeInfo