如何让方法返回特定类型?

时间:2011-01-17 23:17:13

标签: c# generics

我有一个返回基类型的方法,我想要一个重载(最好,但是一个新的方法没问题),而是返回一个父类,这样我就可以这样做:

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

2 个答案:

答案 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;
  }
}