2016-09-10 16 views
0

既知の属性を使用してクラスインスタンスを作成するにはどうすればよいですか? この属性は列挙型の値です。C#クラス属性でクラスインスタンスを作成する方法

public enum MyEnum 
{ 
    Value1, 
    Value2 
} 

class MyAttribute : Attribute... //attribute definition class 
{ //uses the enum} 

//Main 
abstract class MyMain ... 
{ 
    public static MyMain CreateClass 
    { 
     MyMain newInheritedClass = ? 
    } 
} 

[MyAttribute(MyEnum.Value1)] 
class MyClassA : MyMain ... 

[MyAttribute(MyEnum.Value2)] 
class MyClassB : MyMain ... 
+0

[Reflection](https://msdn.microsoft.com/en-us/library/mt656691.aspx)を使用することができますが、実際には何を達成しようとしていますか?おそらくこれを行うにはより良い方法があります。 – InBetween

+0

私はenum値を格納しており、問題の列挙型に基づいて対応するクラスを作成する必要があります。したがって、MyEnum.Value1でコンストラクタを呼び出すと、MyClassAの新しいインスタンスが返されます。 – KSav

+0

はい、それはあなたの質問から明らかです。しかし、なぜこれを行う必要がありますか?このデザインはあなたのものですか?あなたは 'MyMain'と派生クラスを管理していますか、それともサードパーティかコードで変更できないのですか? – InBetween

答えて

0

I:あなたがして属性に基づいてインスタンスを作成するためのタスクを持っている場合はもちろん

public static MyMain CreateInstance(MyEnum attribute) 
{ 
    if(attribute == MyEnum.Value1) 
    { 
     return new MyClassA(); 
    } 
    else 
    { 
     //... 
    } 
} 


ちょうど同じ事を行います方法と静的メソッドまたはファクトリクラスを作成しますcompetelyその使用の属性でFabio's answerがここに行き過ぎと思われるに同意するが、我々は本当に私はそれがどのように行われるかを紹介しますので、あなたがこのアプローチを使用している理由を知るために十分な情報を持っていない:

あなたの方法CreateClassは次のようになります。

  1. あなたの派生クラスを実行するアセンブリで定義されています

    public static MyMain CreateClass(MyEnum value) 
    { 
        var targetType = Assembly.GetExecutingAssembly() 
              .GetTypes() 
              .Where(t => t.IsSubclassOf(typeof(MyMain)) && 
                t.GetCustomAttribute<MyAttribute>()?.Value == value) 
              .FirstOrDefault(); 
    
        if (targetType != null) 
         return Activator.CreateInstance(targetType) as MyMain; 
    
        return null; 
    } 
    

    これには二つのことをpresuposes。

  2. 派生クラスには、パブリックなパラメータのないコンストラクタがあります。

nietherの場合は、まだ少し調べて解決策を適用できます。

+1

'CreateClass'が頻繁に呼び出されている場合は、' GetTypes() 'を一度実行してから、関連する型(非抽象クラスの親クラスのサブクラス)をキャッシュすることをお勧めします。 – flindeberg

+0

@flindebergはい、いい考えです。 – InBetween

0

あなたがコメントで説明する目的のために、私は属性を使用することが少し入札過剰だと思う。

private readonly Dictionary<MyEnum, Type> _Data; 

public Factory(Assembly assembly) 
{ 
    var myAttributeClasses = 
     assembly.GetTypes() 
       .Select(t => new 
       { 
        DirevedType = t, 
        Attribute = (MyAttribute)t.GetCustomAttribute(typeof(MyAttribute)) 
       }) 
       .Where(data => data.Attribute != null); 

    _Data = new Dictionary<MyEnum, Type>(); 
    foreach(var data in myAttributeClasses) 
    { 
     _Data.Add(data.Attribute.EnumValue, data.DerivedType); 
    } 
} 

public MyMain CreateInstance(MyEnum enumvalue) 
{ 
    Type derivedType; 
    if(_Data.TryGetValue(enumvalue, out derivedType) == false) 
     return null; 

    return Activator.CreateInstance(derivedType); 
} 
+0

私は最初にこれを述べておきましたが、if、switchなどの基本クラスのコンストラクタをきれいに保ち、これらの種類のステートメントがない構造体を使ってクラスインスタンスを取得したいと考えています。 – KSav

+0

@KSavどのような基本クラスのコンストラクタ?あなたはファクトメソッドで "ifとswitch"をパッティングしています。そして、 "ifとswitch"の何が間違っていますか?これはプログラミングです...私は泳ぎに行きたいと言っていますが、私は濡れたくありません。 – InBetween

+0

@KSav、とにかくどこかであなたは 'if or switch'を少なくとも一回は入力する必要があります。だから工場のアプローチはあなたが私たちに与えた情報に基づいて良いです。属性を使用することは、アプリケーションのプラグインの可能性を作成するための優れたアプローチです。たとえば、Microsoftには[管理拡張フレームワーク(MEF)](https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110) )。aspx)フレームワークは、 "属性プログラミング"を使用して – Fabio

関連する問題