C# 如何正确使用C++/CLI中实现的类作为.net中数据绑定的数据源?

C# 如何正确使用C++/CLI中实现的类作为.net中数据绑定的数据源?,c#,.net,c++-cli,C#,.net,C++ Cli,我在VC++中定义了一个抽象类,如下所示: public ref class AbstractFoo abstract { public: virtual property String^ Bar { virtual String^ get() = 0; } // More stuff }; public ref class ConcreteFoo : AbstractFoo { public: property String^ Bar {

我在VC++中定义了一个抽象类,如下所示:

public ref class AbstractFoo abstract {
public:
   virtual property String^ Bar {
       virtual String^ get() = 0;
   }

   // More stuff
};
public ref class ConcreteFoo : AbstractFoo {
public:
    property String^ Bar {
        virtual String^ get() override;
    }
    // more
}
internal sealed class FooWrapper {

    private readonly AbstractFoo _foo;

    internal FooWrapper(AbstractFoo foo) {
        _foo = foo;
    }

    public String DisplayName { get { return _foo.Bar; } }

    public static implicit operator AbstractFoo(FooWrapper w) {
        return w._foo;
    }
}
我有很多具体的课程,比如:

public ref class AbstractFoo abstract {
public:
   virtual property String^ Bar {
       virtual String^ get() = 0;
   }

   // More stuff
};
public ref class ConcreteFoo : AbstractFoo {
public:
    property String^ Bar {
        virtual String^ get() override;
    }
    // more
}
internal sealed class FooWrapper {

    private readonly AbstractFoo _foo;

    internal FooWrapper(AbstractFoo foo) {
        _foo = foo;
    }

    public String DisplayName { get { return _foo.Bar; } }

    public static implicit operator AbstractFoo(FooWrapper w) {
        return w._foo;
    }
}
现在,我想在C应用程序的组合框中选择几个AbstractFoo实现之一。因此,我单击组合框上的小箭头并选中使用数据绑定项。然后,我尝试使用AbstractFoo类型创建一个新的数据源。然后单击“完成”时,我得到:

当我关闭对话框时,VS退出。当我使用ConcreteFoo时也会发生这种情况

目前,我能想到的唯一可行的解决方案是用C定义一个类,如下所示:

public ref class AbstractFoo abstract {
public:
   virtual property String^ Bar {
       virtual String^ get() = 0;
   }

   // More stuff
};
public ref class ConcreteFoo : AbstractFoo {
public:
    property String^ Bar {
        virtual String^ get() override;
    }
    // more
}
internal sealed class FooWrapper {

    private readonly AbstractFoo _foo;

    internal FooWrapper(AbstractFoo foo) {
        _foo = foo;
    }

    public String DisplayName { get { return _foo.Bar; } }

    public static implicit operator AbstractFoo(FooWrapper w) {
        return w._foo;
    }
}
然后添加这些FooWrapper,并使用隐式转换返回抽象的Foo

这真的是唯一的方法吗?还是我在VS窒息的地方声明了错误


编辑:在创建GUI时,ConcreteFoo实现已经存在。

我对此进行了更多的研究,并找到了这个问题的原因。就我目前所知,除了上面提到的解决方法外,没有其他解决方法

它与托管/非托管互操作有关。在这个项目中,我仍然绑定到VS2010,所以我不知道这是否只是其中的一个bug,或者是我对事物的错误配置

下面是我如何再现这种行为的:

首先,我创建了一个C++/CLI类库,其中包含一个非常简单的抽象类和具体类,现在我们称它们为AbstractThing和ConcreteThing。然后,我创建了一个简单的C Windows窗体应用程序,其中只包含一个组合框,该组合框绑定到AbstractThing类型的绑定源。这起作用了

然后,我像往常一样将依赖项添加到非托管库中:将非托管库的include目录指定为附加include目录,为调试和发布模式指定包含unmanaged.lib和unmanaged.dll的目录,并将unmanaged.lib添加为附加库。然后,我在C应用程序中添加了一个生成后命令,该命令在成功生成后将相应的unmanaged.dll复制到生成目录中

重新创建绑定仍然有效

现在,让我们来看看游戏的破坏者:

当我向非托管库(如include)添加include时,我收到了上面的错误并退出了VS

为了解决这个问题,我创建了一个如上所述的包装器,起初它可以工作,但导致了下一个奇怪的错误:当我重新进入GUI设计器时,我得到了一个错误页面,我的托管/非托管互操作DLL(包含AbstractThing和ConcreteThing的DLL)找不到。这种情况是:.net的数据绑定分析类的公共属性,如果其中任何一个碰巧属于与非托管内容互操作的类型,事情就会变得疯狂。我相信GUI设计器和VS会在错误的目录中查找依赖的非托管DLL

因此,唯一可行的方法是编写一个包装器,并通过使用内部属性或方法显式地进行提取来隐藏数据绑定中的互操作内容

因此,示例AbstractThing类的包装器现在可以工作了:

internal sealed class ThingWrapper {

    private readonly AbstractThing _thing;

    internal ThingWrapper(AbstractThing thing) {
        _thing = thing;
    }

    public String DisplayName { get { return _thing.SomeStringProperty; } }

    internal AbstractThing Thing { get { return _thing; } }
}

公开内部AbstractThing属性会导致设计器无法正确加载,因此无法使用绑定源的ValueMember属性。提取必须从AbstractThing theThing=ThingWrapper theComboBox.SelectedItem.Thing开始手动完成这里没有C++,但是C++ + CLI是微软扩展到C++的.NET互操作。我已经把C++标签改成C++了。我不知道这有一个额外的标签。我也修改了标题。