Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:将DllImport与继承结合起来?_C#_.net_Windows_Visual Studio 2010_Winapi - Fatal编程技术网

C#:将DllImport与继承结合起来?

C#:将DllImport与继承结合起来?,c#,.net,windows,visual-studio-2010,winapi,C#,.net,Windows,Visual Studio 2010,Winapi,我在尝试将一些代码从java移植到c#时遇到了一些麻烦 首先,对java代码背后的关键概念进行一些解释: 现有代码的关键概念是在外部库中导入/使用方法的类。此类实现了一个接口,该接口声明了外部库中的大多数方法。其好处是能够创建如下实例 Interface1实例=新的classImplementingInterface1() 我正在尝试移植实现接口并从外部库导入方法的代码。实际上,我必须将该接口转换为一个抽象类,因为java接口使用了包含预定义值的字段,这在.NET接口中是不受支持的 这可能是我的

我在尝试将一些代码从java移植到c#时遇到了一些麻烦

首先,对java代码背后的关键概念进行一些解释: 现有代码的关键概念是在外部库中导入/使用方法的类。此类实现了一个接口,该接口声明了外部库中的大多数方法。其好处是能够创建如下实例

Interface1实例=新的classImplementingInterface1()

我正在尝试移植实现接口并从外部库导入方法的代码。实际上,我必须将该接口转换为一个抽象类,因为java接口使用了包含预定义值的字段,这在.NET接口中是不受支持的

这可能是我的出发点:

public abstract class abstractClassA
{
    public abstract int abstractMethodA(int parameter);
}

public class usualClass : abstractClassA
{
    [DllImort("ExternalLib.dll")]
    public static extern abstractMethodA(int parameter);
}
一个抽象类用来从实现该抽象类的类中创建实例,只需键入

abstractClassA instance = new usualClass();
abstractClassA instance = new usualClass();
好的,这就是我想要做的,但我发现这行不通,当我从一个抽象类继承时,我必须对我想要实现的方法使用override语句,比如

public class usualClass : abstractClassA
{
    public extern override abstractMethodA(int parameter);
}
这不能与DllImport语句结合使用,因为它告诉我使用该语句的方法应该同时声明:extern和static。无法添加override关键字来实现抽象类,因为静态成员不能声明为override。所以我想我被一些方法迷住了:/

但实际上我想创建一个类,从外部库命名入口点。但是我希望这个类实现一个接口/抽象类,能够通过键入

abstractClassA instance = new usualClass();
abstractClassA instance = new usualClass();
我还使用一个接口(但没有恼人的静态预定义字段)尝试了这种方法,我发现接口实现也不能与DllImport语句结合使用,编译器说指定的方法是静态的,因此不能实现接口方法。这实际上是有道理的,但并不是解决我问题的合适办法


你有这样或更进一步的想法的经验吗?

你只需要添加一个额外的间接层。您必须用一个C方法重写
AbstractMethodA
,该方法反过来调用外部方法

public abstract class AbstractClassA
{
    public abstract int AbstractMethodA(int parameter);
}

public class UsualClass : AbstractClassA
{
    [DllImport("ExternalLib.dll", EntryPoint="TheFunctionName")]
    private static extern AbstractMethodAExtern(int parameter);

    public override int AbstractMethodA(int parameter)
    {
        return AbstractMethodAExtern(parameter);
    }
}
正如C#编译器所说,该方法必须是
静态外部
。幸运的是,
DllImport
具有
EntryPoint
属性,允许您在C#中使用不同的名称(从而避免命名冲突)。例如:

public abstract class AbstractClassA
{
    public abstract int AbstractMethodA(int parameter);
}

public class UsualClass : AbstractClassA
{
    [DllImport("ExternalLib.dll", EntryPoint = "abstractMethodA")]
    static extern int AbstractMethodAImport(int parameter);
    public override int AbstractMethodA(int parameter)
    {
        return AbstractMethodAImport(parameter);
    }
}
但是,您的代码并没有遵循最佳实践(是的,这是您在Java中命名事物的方式,但在罗马时,您应该是罗马人;请阅读C#命名约定)。您应该按如下方式真正实现它:

public abstract class AbstractClassA
{
    public abstract int AbstractMethodA(int parameter);
}

public class UsualClass : AbstractClassA
{
    public override int AbstractMethodA(int parameter)
    {
        return NativeMethods.AbstractMethodA(parameter);
    }
}

[SuppressUnmanagedCodeSecurity]
internal class NativeMethods
{
    [DllImport("ExternalLib.dll", EntryPoint = "abstractMethodA")]
    public static extern int AbstractMethodA(int parameter);
}

始终将外部对象保存在一个类中,您应该调用
NativeMethods

Hi Jonathan,感谢使用名为NativMethods的内部类的tipp。这是个好主意,我不知道代码约定的事实。