我正在开发一个C#.NET 2.0应用程序,其中在运行时根据环境加载两个DLL中的一个。两个DLL都包含相同的函数,但它们没有链接到相同的地址偏移量。我的问题是关于我的应用程序代码中的函数委托。
public class MyClass
{
public delegate int MyFunctionDelegate(int _some, string _args);
public MyFunctionDelegate MyFuncToCallFrmApp;
public MyClass() : base()
{
this.MyFuncToCallFrmApp = new MyFunctionDelegate(this.MyFuncToCallFrmApp); // <-- Exception thrown here.
}
public SomeFunction()
{
MyFuncToCallFrmApp(int _someOther, string _argsLocal);
}
}
当我的代码执行时,我得到一个ArgumentException
“委托给一个实例方法不能为'''。”我做错了什么?
答案 0 :(得分:11)
您需要将一个有效的函数(由动态加载的dll中的某个类托管)分配给您的委托变量。如果函数是具有同名的类的静态方法,那么这很简单:
public MyClass() {
this.MyFuncToCallFrmApp = ExternalClass.Function;
}
如果函数是具有相同名称的类的实例方法,则只需创建一个实例并执行相同的操作(另请注意,只要委托在范围内,它将阻止ExternalClass
实例垃圾收集 - 您可能希望将实例存储为成员变量以使其更清晰):
public MyClass() {
this.MyFuncToCallFrmApp = new ExternalClass().Function;
}
如果动态加载的类具有不同的名称,则需要确定要调用哪一个 - 在本例中,我使用布尔成员变量来决定是否使用默认程序集的类:
public MyClass() {
if (this.defaultAssembly) {
this.MyFuncToCallFrmApp = ExternalClass1.Function;
} else {
this.MyFuncToCallFrmApp = ExternalClass2.Function;
}
}
答案 1 :(得分:10)
在你的行中:
this.MyFuncToCallFrmApp = new MyFunctionDelegate(this.MyFuncToCallFrmApp);
在分配之前使用“this.MyFuncToCallFrmApp”,这意味着在分配期间它为空。让代表指向自己毫无意义。那是你想要做的吗?
答案 2 :(得分:4)
您正在尝试使用已经在您的类中的委托的未初始化实例来创建委托的新实例...这没有任何意义。
您需要使用类中具有匹配参数列表作为代理的方法初始化委托,或者不初始化委托并允许类的使用者使用其代码中的匹配方法初始化委托(这是代表通常使用的内容):
public class MyClass
{
public delegate int MyFunctionDelegate(int some, string args);
public MyFunctionDelegate MyFuncToCallFrmApp;
public MyClass() : base() { }
public SomeFunction()
{
if(MyFuncToCallFrmApp != null)
MyFuncToCallFrmApp(_someOther, _argsLocal);
}
}
public class Consumer
{
MyClass instance = new MyClass();
public Consumer()
{
instance.MyFuncToCallFrmApp = new MyFunctionDelegate(MyFunc);
}
public void MyFunc(int some, string args)
{
// Do Something
}
}
答案 3 :(得分:3)
吉姆,我正在尝试用C#自己学习代表。
您的代码存在的一个问题是您尚未将委托分配给有效的处理程序。委托的签名必须与具有相同方法签名的有效处理程序匹配。
在行中:
this.MyFuncToCallFrmApp = new MyFunctionDelegate(this.MyFuncToCallFrmApp);
this.MyFuncToCallFrmApp
是委托,但它必须是有效的方法处理程序。
以下是传递方法处理程序的方法:
public delegate int MyFunctionDelegate(int _some, string _args);
MyFunctionDelegate MyFuncToCallFrmApp = new MyFunctionDelegate(PrintValues);
// the method I'm mapping has a valid signature for the delegate I'm mapping to:
public void PrintValues(int some, string args)
{
Console.WriteLine(string.Format("Some = {0} & Args = {1}", some.ToString(), args));
}
希望下面的链接和示例代码对您有所帮助:
<强> Delegates Tutorial 强>
C#中的委托类似于C或C ++中的函数指针。使用委托允许程序员封装对委托对象内的方法的引用。然后可以将委托对象传递给可以调用引用方法的代码,而无需在编译时知道将调用哪个方法。与C或C ++中的函数指针不同,委托是面向对象的,类型安全的和安全的。 (MSDN)
public class MyClass
{
// a delegate by definition is a collection of pointers to method handlers
// I declare my delegate on this line
// PLEASE NOTE THE SIGNATURE!
public delegate void MyFunctionDelegate(int some, string args);
public MyClass() : base()
{
// instantiate the delegate (AKA create the pointer)
MyFunctionDelegate myFunctionDelegate = new MyFunctionDelegate();
// map a valid method handler (WITH THE SAME SIGNATURE) to this delegate
// I'm using "+=" operator because you can add more than one handler to a collection
myFunctionDelegate += new MyFunctionDelegate(PrintValues);
// invoke the method handler (which in this case is PrintValues() - see below)
// NOTE THE SIGNATURE OF THIS CALL
myFunctionDelegate(1, "Test");
}
// this is the handler method that I am going to map to the delegate
// AGAIN, PLEASE NOTE THE SIGNATURE
public void PrintValues(int some, string args)
{
Console.WriteLine(string.Format("Some = {0} & Args = {1}", some.ToString(), args));
}
}
答案 4 :(得分:2)
您正在尝试初始化委托以调用自身。你从根本上做的事情没有意义。