我有一个返回基类型的方法,我想要一个重载(最好,但是一个新的方法没问题),而是返回一个父类,这样我就可以这样做:
DynamicClass cl = new DynamicClass(...);
var dict = cl.CreateObject<DynamicDictionary>("ClassName");
dict.CallAddOnMethod("test");
这是我尝试过的代码,但我似乎无法访问DynamicDictionary
public sealed class DynamicClass : DynamicBaseClass
{
public DynamicObject CreateObject(params object[] args)
{
Debug.Assert(args.Length > 0);
object handle = InvokeMethod(CreateObjectMethod, args);
return new DynamicObject(bcAssembly, (string)args[0], handle);
}
public T CreateObject<T>(params object[] args)
{
Debug.Assert(args.Length > 0);
object handle = InvokeMethod(CreateObjectMethod, args);
DynamicObject item = new DynamicObject(bcAssembly, (string)args[0], handle)
return (T)item; // cant do this?
}
}
public class DynamicObject : DynamicBaseClass
{
private const string CallMethod = "Call";
public DynamicObject(Assembly assembly, string parentName, object classHandle)
: base(assembly, parentName, classHandle)
{
}
public object Call(string methodName, params object[] paramList)
{
return InvokeMethod(CallMethod, paramList);
}
}
public sealed class DynamicObject<T> : DynamicObject
{
private const string CallMethod = "Call";
public DynamicObject(Assembly assembly, string parentName, object classHandle)
: base(assembly, parentName, classHandle)
{
}
}
public sealed class DynamicDictionary : DynamicObject
{
private const string AddOnMethod = "AddOn";
public DynamicDictionary(Assembly assembly, string parentName, object classHandle)
: base(assembly, parentName, classHandle)
{
}
public int CallAddOnMethod(string name)
{
return (int)Call(AddOnMethod, name);
}
}
答案 0 :(得分:1)
在模板中,您应该要求类型是动态对象的子类:
即
var blah_b = test<b>();
blah_b.Dump();
var blah_c = test<c>();
blah_c.Dump();
-
public T test<T>() where T : a
{
var item = Activator.CreateInstance(typeof(T));
return (T)(item);
}
public class a
{
}
public class b : a
{
}
public class c : a
{
}
答案 1 :(得分:0)
另一种方法是加载代码,编译代码并动态执行编译结果。以下示例使用私有字符串作为模板代码源(您可以从文本文件加载它):
using Microsoft.CSharp;
public class MyTemplate : IDisposable {
private const string _SourceCodeTemplate = @"
using System;
public class {0} {{ // {{0}} Class name
public {0} CreateInstance()
{{
{0} instance;
//... some codes here to create instance
return instance;
}}
public {1} {2}() {{ // {{1}} method result, {{2}} method name
{1} result;
// some codes here for the result
return result;
}}
}}";
public T CallInstanceMethod<T>(string className, string callMethod,
string callMethodResult,
params object[] paramList) {
string codes;
// build codes dynamically
codes = string.Format(_SourceCodeTemplate, className,
callMethodResult, callMethod);
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
parameters.IncludeDebugInformation = false;
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
parameters.ReferencedAssemblies.Add(asm.Location);
}
// compile the codes
CompilerResults cr= codeProvider.CompileAssemblyFromSource(parameters, codes);
var csInstance = cr.CompiledAssembly.CreateInstance(className);
Type type = csInstance.GetType();
var methodForInstance = type.GetMethod(callMethod);
object value;
value = _methodForInstance.Invoke(csInstance, paramList);
return (T)value;
}
}