2017-07-27 68 views
-1

我製作了項目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() { } 
} 

然後,我在我的解決方案參考創建第二個項目,這是我的主類:

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

我想實現「狗,狗」,「貓,貓」,「老鼠,老鼠」 。其中,「狗」是name屬性和「狗」是一種感謝,我將能夠使像

Activator.CreateInstance(animals[nameAnimal]); 

但現在我做錯了什麼,我的方法不工作,我無法找到工作解決我的問題.net核心。我只想從屬性方法的類中獲得對象。如何實現它?

編輯。 我的程序沒有看到圖書館「狗」,搜索例如參考,Ref.Program等

+0

*什麼*不工作? – InBetween

+0

您是否使用Visual Studio? –

+0

@JonathanWillcock是的,2017 – nju

回答

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 { ... } 
    
+0

我無法訪問GetCustomAttribute()... – nju

+0

@nju那很奇怪。你有正確的名稱空間聲明:'使用System.Reflection'?這應該使[[CustomAttributeExtensions.cs]](https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Reflection/CustomAttributeExtensions.cs)提供的擴展方法可用。我的項目中的 – InBetween

+0

t是一個Type,並且不包含此方法。是的,我有'使用System.Reflection' – nju

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

     } 
+0

'類型'不包含'GetCustomAttributesData'的定義 – nju

+0

它包含@nju – Koderzzzz

+0

對我來說工作正常.. – Koderzzzz

0

對不起,我以前的愚蠢。我多花了一點時間,再讀一遍。我現在認爲我理解你的問題。你想知道的是爲什麼使用反射你沒有看到你的其他兩個類?原因很簡單:這兩個類不在同一個程序集中!你的第一個項目編譯成一個dll。這是它自己的程序集。您的第二個項目編譯爲另一個程序集的exe文件。因此,在第二個裝配中使用反射,僅向第二個裝配中的類型顯示。

爲了得到你想要的,只需從圖書館移動你的狗班,並將它們包含在你的第二個項目中。然後你將能夠在Main中看到它們。

編輯

使用此:

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

假設您編譯解決方案一起,然後DLL應該是在同一個bin文件夾作爲你的EXE。否則,你需要給全路徑。

+0

是的,這不是壞的解決方案,但我必須將其保存在不同的項目(庫)中。所以我需要搜索這個DLL? – nju

+0

程序集不包含ReflectionOnlyLoadFrom。我正在使用.net核心 – nju

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

仍行t.GetCustomAttributesData();錯誤 - 「類型」不包含定義.... – nju

0

您可以使用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); 
     } 
    } 
}