如何使用反射将一个未知类的实例用作方法调用的参数?

时间:2010-07-28 21:35:32

标签: c# .net reflection

确定这笔交易,我从网络服务中获取所有方法并提供测试方法。到目前为止,我们正在显示他们的方法,一些方法只处理整数和字符串。那部分是照顾的。 (我们可以正确调用方法并解析结果)

问题是方法调用所需的一些参数是在Web服务中某处定义的类,我们无法知道它们是什么。我们唯一知道的是这些类只由字符串和整数组成。 (耶)

让我说我希望在运行时创建一个类型为“Agent”的实例。

到目前为止,我可以访问在运行时加载的服务,该服务位于不同的类中。这很好用

代理类:

.
.
.
CompilerParameters parms = new CompilerParameters(assemblyReferences);      
CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
// Checks For Errors
// add the web service method to our list of methods to test
//--------------------------------the following variables are class level ---------------------------
object service = results.CompiledAssembly.CreateInstance(serviceName);
Type types = service.GetType();
List<ConstructorInfo> listConstructors = (service as Types).GetType().GetConstructors().ToList();
List<MethodInfo> listMethods = types.GetMethods().ToList();

listMethods.Where(mi => mi.GetCustomAttributes(false).
    Where(at => at.GetType() == typeof(SoapDocumentMethodAttribute)).
    Count() > 0).ToList().ForEach(methodsInfo =>{
           //methods to test is a list of a wrapper class for methodInfos
            MethodsToTest.Add(new MethodTest(methodsInfo));
        });

现在,在另一个类中工作。我试图通过调用方法来获取我们需要的类型的对象:

我正在尝试制作这个“Agent”类的实例

private void populateParameterListView(){
            if (funcLBox.SelectedItem != null)
            {
                resultTBlock.Text = String.Empty; //our textbox
                paramLView.Items.Clear();
                ParameterUserInput pui = null; //a wrapper class for parameterinfo
                Proxy.MethodsToTest[index].info.ToList().ForEach(param =>
                {
                pui = new ParameterUserInput(param);
                paramLView.Items.Add(pui);
                //this will check if it is a system type or a custom type
                if (!pui.ParameterType.IsSealed) 
                { 
                   // this is where we want to be. nevermind the code above this
                   //temp in this case is "Agent"
                   string temp = Proxy.MethodsToTest[index].info.GetValue(0).ToString().Split(' ')[0];

                   MemberInfo[] mia = Proxy.types.GetMember(temp);
                   //get an object of the type we need by invoking the method
                }
            });

    }

截至目前,它试图通过在代理上执行get成员来通过代理中声明的“类型”来搜索成员。问题是,我很确定我仍然会在那些成员的错误位置寻找。任何人都可以看到我做错了什么?我知道它与实际迭代的内容有关。

2 个答案:

答案 0 :(得分:0)

好的,这可能是一个延伸,但Json for .Net库(json.codeplex.com)将允许您从任何类构造对象。

例如(来自他们的文档)

Product product = new Product();

product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string output = JsonConvert.SerializeObject(product);

//{
//  "Name": "Apple",
//  "Expiry": "\/Date(1230375600000+1300)\/",
//  "Price": 3.99,
//  "Sizes": [
//    "Small",
//    "Medium",
//    "Large"
//  ]
//}

Product deserializedProduct = JsonConvert.DeserializeObject<Product>(output);

这将很容易处理你的整数和字符串。

唯一的问题是获得JsonConvert.DeserializeObject<T>(),您可以轻松地使用您的反思技能。

编辑:以下是必备的反思技巧。

object ParseUserInput(string jsonInput)
{
  Type type = <get type instance somehow>

  var json = typeof(JsonConvert);
  var generic = json.GetMethods().Where(m => 
       m.Name == "DeserializeObject" &&
       m.GetParemeters().Count == 1).Single();
  var method = generic.MakeGenericMethod(type);

  return method.Invoke(null, jsonInput);
}

答案 1 :(得分:0)

我所做的是获取编译器结果并尝试在那里查找类型。 我使编译器结果成为一个类级变量,我稍后会重复使用。

CompilerResults = provider1.CompileAssemblyFromDom(parms, unit1);

然后我访问了它并获得了我正在寻找的类的类型

CompilerResults.CompiledAssembly.GetType(temp)

在这种情况下,temp是我在webservice中寻找的自定义类的名称

获得类型后,您可以获取构造函数,属性和方法信息