2017-10-08 7 views
0

新しいオブジェクトが追加されたときに常に新しい行を追加する必要があるため、スイッチオブジェクトではなく1つのコード行で正しいオブジェクトを生成します。オブジェクトのリフレクションc#

スイッチケースを使用せずに1行で行うことはできますか?

public static Device GetDevice(Device.enumDevice TypeOfDevice, string alias) 
{ 
    // Create the Object with using reflection 

    switch (TypeOfDevice) 
    { 
     case Device.enumDevice.A34411: 
      return new A34411(string alias); 
      break; 
     case Device.enumDevice.N5744: 
      return new N5744(string alias); 
      break; 
     default: 
      throw new NotImplementedException(); 
    } 

    return null; 
} 
+0

反射はどこですか? – oerkelens

+1

クラスにカスタム属性を置き、リフレクションを使用して、 'Device'ベースクラスのすべてのサブクラスを列挙し、その属性を正しい値で探します。 –

+1

あなたの計画もenumの使用を削除することですか? –

答えて

0

エレガントなアプローチは

3

あなたが使用して辞書

private static Dictionary<Device.enumDevice, Func<string, Device>> _factoryDict = 
    new Dictionary<Device.enumDevice, Func<string, Device>>{ 
     [Device.enumDevice.A34411] = (alias) => new A34411(alias), 
     [Device.enumDevice.N5744] = (alias) => new N5744(alias), 
    }; 

... 

public static Device GetDevice(Device.enumDevice TypeOfDevice, string alias) 
{ 
    if (_factoryDict.TryGetValue(TypeOfDevice, out var factory)) { 
     return factory(alias); 
    } 
    throw new NotImplementedException(); 
    // No retun statement here, as it would be unreachable because of the throw statement. 
} 

か、で代表者としてファクトリメソッドを格納することができ、「名前付きタイプ登録」と依存性の注入を使用することです反射:

const string deviceNameSpace = "MyName.MyProject.Devices."; 

public static Device GetDevice(Device.enumDevice deviceType, string alias) 
{ 
    string typeName = deviceNameSpace + deviceType.ToString(); 
    Type type = Type.GetType(typeName, throwOnError: true); 
    return (Device)Activator.CreateInstance(type, alias); 
} 
+0

2番目の例が正しくありません。 Type.GetTypeには、最も単純な場合は "namespace.class"が必要ですが、完全なAssemblyQualifiedNameを使用する方が適切です。 – arndtdv

+0

@arndtdv:そうです。クラスが同じアセンブリ内にある場合は、AssemblyQualifiedNameを省略できます。 –

0

高速ですが、完全な例ではありません。

public abstract class Device 
{ 
    protected Device(string alias) 
    { 
     Alias = alias; 
    } 
    public string Alias { get; } 
} 

public class A1 : Device 
{ 
    public A1(string alias) : base(alias) { } 
} 

public class A2 : Device 
{ 
    public A2(string alias) : base(alias) { } 
} 

class DeviceAttribute : Attribute 
{ 
    public DeviceAttribute(Type type) 
    { 
     Type = type; 
    } 

    public Type Type { get; } 
} 

public enum DeviceEnum 
{ 
    [Device(typeof(A1))] 
    A1, 
    [Device(typeof(A2))] 
    A2 
} 

public static class DeviceEnumExtension 
{ 
    public static Device GetInstance(this DeviceEnum obj, string alias) 
    { 
     var member = typeof(DeviceEnum).GetMember(obj.ToString()); 

     if (member[0].GetCustomAttributes(typeof(DeviceAttribute), false)[0] is DeviceAttribute deviceAttr) 
     { 
      var ctor = deviceAttr.Type.GetConstructor(new[] {typeof(string)}); 
      return ctor.Invoke(new object[] {alias}) as Device; 
     } 
     return null; 
    } 
} 

public class UnitTest1 
{ 
    [Fact] 
    public void Test1() 
    { 
     // Arrange 
     var a1 = DeviceEnum.A1; 
     var a2 = DeviceEnum.A2; 

     // Act 
     var instanceA1 = a1.GetInstance("A1"); 
     var instanceA2 = a2.GetInstance("A2"); 

     // Assert 
     Assert.Equal(typeof(A1), instanceA1.GetType()); 
     Assert.Equal(typeof(A2), instanceA2.GetType()); 
     Assert.Equal("A1", instanceA1.Alias); 
     Assert.Equal("A2", instanceA2.Alias); 
    } 
} 
関連する問題