私はC#のの動的部分の専門家ではないんだけど、これは正しく動作しているようです:
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using Microsoft.CSharp.RuntimeBinder; // Requires reference to Microsoft.CSharp
public class ImplicitTest
{
public double Val { get; set; }
public ImplicitTest(double val)
{
this.Val = val;
}
public static implicit operator int(ImplicitTest d)
{
return (int)d.Val;
}
}
public class TestClass
{
public int Val { get; set; }
public TestClass(int val = 5)
{
this.Val = val;
}
public TestClass(int val1, int val2)
{
this.Val = val1 + val2;
}
public TestClass(int val1, int val2, int val3, int val4, int val5, int val6, int val7, int val8, int val9, int val10, int val11, int val12, int val13, int val14)
{
this.Val = val1 + val2 + val3 + val4 + val5 + val6 + val7 + val8 + val9 + val10 + val11 + val12 + val13 + val14;
}
}
public static class DynamicFactory
{
private static readonly CallSiteBinder callsiteBinder0 = Binder.InvokeConstructor(
CSharpBinderFlags.None,
typeof(DynamicFactory),
// It is OK to have too many arguments :-)
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType, null), // 0 parameters
});
private static readonly CallSiteBinder callsiteBinder = Binder.InvokeConstructor(
CSharpBinderFlags.None,
typeof(DynamicFactory),
// It is OK to have too many arguments :-)
// Note that this "feature" doesn't work correctly with Mono in the
// case of 0 arguments
new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType, null), // 0 parameters
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), // 1 parameter
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), // 2 parameters
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), // 14 parameters
});
// Quirk of Mono with 0 arguments. See callsiteBinder0
private static readonly CallSite<Func<CallSite, Type, object>> CallSite0 = CallSite<Func<CallSite, Type, object>>.Create(callsiteBinder0);
private static readonly CallSite<Func<CallSite, Type, object, object>> CallSite1 = CallSite<Func<CallSite, Type, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object>> CallSite2 = CallSite<Func<CallSite, Type, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object>> CallSite3 = CallSite<Func<CallSite, Type, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object>> CallSite4 = CallSite<Func<CallSite, Type, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object>> CallSite5 = CallSite<Func<CallSite, Type, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object>> CallSite6 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object>> CallSite7 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object>> CallSite8 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object>> CallSite9 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object>> CallSite10 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object>> CallSite11 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object, object>> CallSite12 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object, object, object>> CallSite13 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
private static readonly CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>> CallSite14 = CallSite<Func<CallSite, Type, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object>>.Create(callsiteBinder);
public static object Create(string typeName, params object[] args)
{
return Create(Type.GetType(typeName), args);
}
public static object Create(Type type, params object[] args)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
if (args == null)
{
args = new object[0];
}
object obj;
switch (args.Length)
{
case 0:
// Quirk of Mono with 0 arguments. See callsiteBinder0
obj = CallSite0.Target(CallSite0, type);
break;
case 1:
obj = CallSite1.Target(CallSite1, type, args[0]);
break;
case 2:
obj = CallSite2.Target(CallSite2, type, args[0], args[1]);
break;
case 3:
obj = CallSite3.Target(CallSite3, type, args[0], args[1], args[2]);
break;
case 4:
obj = CallSite4.Target(CallSite4, type, args[0], args[1], args[2], args[3]);
break;
case 5:
obj = CallSite5.Target(CallSite5, type, args[0], args[1], args[2], args[3], args[4]);
break;
case 6:
obj = CallSite6.Target(CallSite6, type, args[0], args[1], args[2], args[3], args[4], args[5]);
break;
case 7:
obj = CallSite7.Target(CallSite7, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
break;
case 8:
obj = CallSite8.Target(CallSite8, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
break;
case 9:
obj = CallSite9.Target(CallSite9, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
break;
case 10:
obj = CallSite10.Target(CallSite10, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
break;
case 11:
obj = CallSite11.Target(CallSite11, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]);
break;
case 12:
obj = CallSite12.Target(CallSite12, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]);
break;
case 13:
obj = CallSite13.Target(CallSite13, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]);
break;
case 14:
obj = CallSite14.Target(CallSite14, type, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]);
break;
default:
throw new ArgumentException("Too many parameters");
}
return obj;
}
}
public class Program
{
public static void Main()
{
try
{
Type monoRuntime = Type.GetType("Mono.Runtime");
if (monoRuntime != null)
{
System.Reflection.MethodInfo displayName = monoRuntime.GetMethod("GetDisplayName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (displayName != null)
{
Console.WriteLine("Mono version {0}", displayName.Invoke(null, null));
}
}
TestClass tc0 = (TestClass)DynamicFactory.Create("TestClass");
TestClass tc1 = (TestClass)DynamicFactory.Create("TestClass", new ImplicitTest(1.0));
TestClass tc1b = (TestClass)DynamicFactory.Create("TestClass", 1);
TestClass tc2 = (TestClass)DynamicFactory.Create("TestClass", new ImplicitTest(1.0), new ImplicitTest(2.0));
TestClass tc14 = (TestClass)DynamicFactory.Create("TestClass", Enumerable.Range(0, 14).Select(x => new ImplicitTest((double)x)).ToArray());
Console.WriteLine(tc0.Val);
Console.WriteLine(tc1.Val);
Console.WriteLine(tc1b.Val);
Console.WriteLine(tc2.Val);
Console.WriteLine(tc14.Val);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
これは、.NETの「動的」部分を活用しています。それはMicrosoft.CSharp.RuntimeBinderを使用してC#のバインディングルールを "認識"しています。他の誰かが指摘したように、ユーザー定義の暗黙的キャストと明示的キャストは.NETのものではなくC#のものなので、バインダーが必要です。完璧なソリューションは、C#のルールを "知っている" System.Reflection.Binder
クラスのサブクラスを持つことです。その後、それをType.GetConstructor
に渡し、幸せに生きることができます。残念ながらそのような実装はありません。
悲しいことに、デリゲートはCallSite
、CallSite<T>
の汎用サブクラスに格納され、T
はデリゲートタイプです。このため、大きいswitch
命令。
コードのアイデア:https://ideone.com/NoQ67H。 Monoにはquirkがあるので、0のコンストラクタには特別な処理があります。あなたはここで、式フレームワークを利用することができ
似たようなスレッド:http://stackoverflow.com/questions/20932208/activator-createinstance-not-working-for-implicit-cast-scenario –
「暗黙の演算子int」は「静的」なのでしたがって、 'object'クラスのメソッドをオーバーライドしません。そして、 'Activator.CreateInstance'を渡すと、あなたが渡す' Args'は 'object'sです。 –
.NETの動的インフラストラクチャを活用することは可能です。 'Microsoft.CSharp'アセンブリには、オーバーロード選択のためのC#"規則 "があります。 https://ideone.com/UkGm4Eを参照してください。私は "ジェネリック"作業メソッド(ダイナミックはC#の私のフィールドではありません)に変換するのに十分なエキスパートではありません – xanatos