你有一點設計問題。您有一個包含您發佈的示例反射代碼的程序集(我們稱之爲程序集A)。您還有第二個程序集(我們稱之爲程序集B),它包含MyClass和Test。
問題是,在您的反射代碼中,您正嘗試創建Test類的實例,以便您可以將其作爲參數傳遞給MyClass.MyFunction。
您提到您已將Test類的源代碼複製到程序集A中;這是行不通的。你在那裏做的實質上是創建兩個具有相同名稱和相同結構的不同類。由於這兩個類與CLR並不相同,因此如果您試圖將其中一個投射到另一個類上,您將獲得無效的投射異常。
鑑於迄今爲止發佈的內容,在我看來,對於您的方法最直接的解決方案是擁有第三個程序集(我們稱之爲程序集C),其中包含組件A和B都已知的組件。在解決方案中創建一個類庫項目,將Test類移入該項目,擺脫前兩個項目中任何其他類的Test類,並在引用新項目的前兩個項目中添加引用。一旦你這樣做了,程序集A和程序集B都將引用Test類的同一個類定義,並且你發佈的示例代碼將會工作。
但讓我指出一些事情。如果程序集A中的代碼不能充分了解程序集B中的代碼,以便實例化MyClass並直接調用MyFunction(而不是通過反射),那麼它如何知道足夠的代碼知道要傳遞哪些參數? MyFunction是否具有程序集A能夠理解的通用方法簽名?如果是這樣的話,那麼MyClass的可能應該執行該組件中的知道,這樣裝配一個可以直接調用MyFunction的,如下圖所示的界面:
Assembly assembly = Assembly.Load("MyProject.Components");
Type dllType = assembly.GetType("MynameSpace.MyClass");
if (dllType != null)
{
IMyInterface instance = Activator.CreateInstance(dllType) as IMyInterface;
if (instance != null) // check if this object actually implements the IMyInterface interface
{
instance.MyFunction(objTest);
}
}
如果這似乎並不像你想的方法,那麼還有其他選擇。由於看起來您不希望程序集A具有對程序集B的直接引用,因此如果您將程序集的類保留在程序集B的內部,那麼程序集A沒有任何方法可以使用任何有關Test類的知識以構建一個。在這種情況下,您可以使用工廠模式方法,基本上這樣程序集A就知道某種能夠實例化Test對象的工廠對象。下面是一個實現的例子:
我上面提到關於創建第三個項目。我仍然建議這樣做。在我的例子中,我命名了我的「MyProject.Common」。它包含以下代碼:
// define a simple factory interface
public interface IFactory
{
object CreateInstance();
}
// and a generic one (hey, why not?)
public interface IFactory<T> : IFactory
{
new T CreateInstance();
}
// define a Factory attribute that will be used to identify the concrete implementation of a factory
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class FactoryAttribute : Attribute
{
public Type FactoryType { get; set; }
public FactoryAttribute(Type factoryType)
{
this.FactoryType = factoryType;
}
}
的IFactory接口和工廠屬性將被已知的,在我的解決方案由其他項目的理解,因爲它們均引用MyProject.Common項目。
下面是包含我的「MyProject.Components」項目中的代碼:
public class Test
{
public string Name { get; set; }
public string Type { get; set; }
public Test(string name, string type)
{
this.Name = name;
this.Type = type;
}
}
public class TestFactory : IFactory<Test>
{
#region IFactory<Test> Members
public Test CreateInstance()
{
return new Test("name", "type");
}
#endregion
#region IFactory Members
object IFactory.CreateInstance()
{
return this.CreateInstance();
}
#endregion
}
public class MyClass
{
// the Factory attribute on the first parameter indicates that the class TestFactory
// should be used as a factory object to construct the argument for this method
public string MyFunction([Factory(typeof(TestFactory))]Test obj)
{
if (obj == null)
return null;
else
return obj.ToString();
}
}
最後,我把它換成你貼有原始反射代碼如下:
Assembly assembly = Assembly.Load("MyProject.Components");
Type dllType = assembly.GetType("MynameSpace.MyClass");
if (dllType != null)
{
MethodInfo m = dllType.GetMethod("MyFunction");
object objdll;
objdll = Activator.CreateInstance(dllType);
// use the parameter information to construct the arguments
ParameterInfo[] parameters = m.GetParameters();
object[] args;
if (parameters != null && parameters.Length > 0)
{
args = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
// check for factory attributes on the actual parameter
FactoryAttribute[] attributes = parameters[i].GetCustomAttributes(typeof(FactoryAttribute), true) as FactoryAttribute[];
// if no attributes were found, check the parameter type for factory attributes
if (attributes == null || attributes.Length == 0)
attributes = parameters[i].ParameterType.GetCustomAttributes(typeof(FactoryAttribute), true) as FactoryAttribute[];
// if no attributes were found still, then give up
if (attributes == null || attributes.Length == 0)
{
// this parameter has no factory specified,
// so how would this code know how to create the argument for that parameter ???
args[i] = null;
continue; // move on to the next parameter
}
// there should only be one factory attribute, so use the first one
// assumption made here is that all factory classes will have a parameterless constructor
IFactory factory = Activator.CreateInstance(attributes[0].FactoryType) as IFactory;
args[i] = factory.CreateInstance();
}
}
else
// there are no parameters
args = null;
if ((m != null))
{
strReturnValue += (string)m.Invoke(objdll, args);
}
}
請包括您試圖調用的方法簽名(''MyFunction',具體來說,就是'dllType.GetMethod(「MyFunction」);')。另外,異常在哪裏發生? – Femaref 2010-09-07 11:38:05