【问题标题】:Typedefs, C++/CLI, C# + dependency injectionTypedefs, C++/CLI, C# + 依赖注入
【发布时间】:2013-05-27 07:47:10
【问题描述】:

我有一个用 C# 编写的专用字典,它接受两个通用参数。界面是

public interface IMyDictionary<TKey, TValue> { ... }

及其实现之一

public MyDictionary<TKey, TValue> {...}

我还有一个复杂的 C++ 模板结构,我在我的 C++/CLI ref 类中 typedef:

typedef boost::some_complex_template<stuff>    MySimpleValueType;

在我的 C++/CLI ref 类构造函数中,我曾经创建字典的实例:

MyCppCliClass::MyCppCliClass()
    : _my_dict(gcnew MyDictionary<MySimpleValueType, Something^>())
{...}

现在,如果你喜欢依赖注入,你会发现这很糟糕。理想情况下,我应该有一个这样的构造函数:

MyCppClass::MyCppCliClass(IMyDictionary<MySimpleValueType, Something^>^ dict){...}

这个类是用 C# 实例化的,所以现在我的问题是:

鉴于(afaik)C++ 模板 typedef 和纯 C++ 类型在 C# 中可用,我如何实例化我现在在 C++/CLI 之外使用的这个有效的 ref 类?

MySimpleValueType 显然必须是 C# 的原生类型,否则 Dictionary 的实例化将失败:

error C3225: generic type argument for 'T1' cannot be '...', it must be a value type
> or a handle to a reference type.

我觉得我应该能够在 C++/CLI 类中定义类型(使用 typedef),但是从外部实例化 Dictionary。 C++/CLI typedefs 在 C# 中不可用,所以也许有一种方法可以对 var 进行 getter 和类型推导?有什么想法吗?

【问题讨论】:

  • 如果 MySimpleType 在该字典中可用,这是否意味着它实际上是一个有效的ValueType(例如boost::some_complex_template&lt;stuff&gt;::number_type 原来是int)?
  • 在调试器中查看它,它告诉我这是一个 IMyDictionary。但我不认为我可以依赖它,因为类型取决于 typedef,而 typedef 又取决于各种其他 typedef (boost, yknow ;))。
  • 我相信如果你的 C++/CLI 代码不是对 CLR 有效的类型(如 unsigned __int64/System::UInt64),它就不会编译。所以我猜如果你的代码编译,C#代码可以链接到它。 (毕竟,您实际上并没有向其他程序集公开模板,只有模板实例化结果和泛型)
  • 是的,这也是我的结论。我更新了问题。我认为主要问题是我在 C++/CLI 中制作的 typedef 在 C# 中不可见。

标签: c# c++ dependency-injection c++-cli


【解决方案1】:

boost 是一个未管理的库。该错误消息告诉您不能在通用托管类中使用非托管类型。

要解决此问题,请创建一个托管类来容纳您的非托管类,并在容器中使用它。

public ref class MySimpleValueTypeHolder
{
private:
    MySimpleValueType* unmanaged;

public:
    property MySimpleValueType* ValueType { 
        MySimpleValueType* get() { return this->unmanaged; }
    }

    MySimpleValueTypeHolder() { this->unmanaged = new MySimpleValueType(); }
    ~MySimpleValueTypeHolder() { this->!MySimpleValueTypeHolder(); }

    !MySimpleValueTypeHolder()
    {
        if(this->unmanaged != nullptr)
        {
            delete this->unmanaged;
            this->unmanaged = nullptr;
        }
    }
};

Dictionary<MySimpleValueTypeHolder^, Something^>^ foo;

【讨论】:

  • 这是解决另一个问题的好方法。 boost typedef 计算为一个值类型,该值类型可以用作我的 C# 字典的键;它是某种类型的 int,签名和位大小取决于模板。但我无法从 C# 中的类中“获取”值类型,因为它是 C++ typedef,对 C# 不可见。
  • C++ typedef 无关紧要。您在 C# 中看到的是替换实际类定义的结果。它不起作用的原因是因为 boost typedef 不是 value 类型,它是一个 unmanaged 类型。
  • 请再次阅读问题。很抱歉,但我的问题不在于它是非托管类型。这是我无法找出 typedef 匹配的特定值类型。我确实尝试过使用非值类型,我什至提到了使用非值时得到的错误类型以表明它是值类型(因为我没有得到那个错误)。
猜你喜欢
  • 2011-07-14
  • 2014-02-20
  • 2010-12-26
  • 2010-09-26
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多