简体   繁体   English

如何在控制台程序和DLL之间使用通用的类/接口?

[英]How to use a common Class/Interface between a Console Program and a DLL?

I"m developing an application (.NET framework + C#) where I have a bunch of DLLs developed and sent to me by clients, which I put in a folder and read from my main console program. For the sake of simplicity, I'll explain it using a rather abstract example which properly represent my original problem. 我正在开发一个应用程序(.NET framework + C#),其中有一些由客户端开发并发送给我的DLL,我将它们放在一个文件夹中并从主控制台程序中读取。为简单起见,我将我会用一个相当抽象的例子来解释它,它能恰当地代表我的原始问题。

I want the DLLs to have one function, which creates and returns an object of the data type "PersonData". 我希望DLL具有一个函数,该函数创建并返回数据类型为“ PersonData”的对象。 PersonData has three variables, namely, personName, personAge, and personNationality. PersonData具有三个变量,即personName,personAge和personNationality。 The data type PersonData, which is a structure, look like this: 数据类型PersonData是一种结构,如下所示:

namespace CommonStuff
{
    public static class Common
    {
        public struct PersonData
        {
            string name;
            int age;
            string nationality;

            // Properties go here.

            // Constructor goes here.
        }
    }
}

The above is saved in a file called Common.cs. 以上内容保存在一个名为Common.cs的文件中。

Then I have an interface, which is saved in IPerson.cs which looks like this: 然后,我有一个接口,该接口保存在IPerson.cs中,如下所示:

namespace CommonStuff
{
    public interface IPerson
    {
        Common.PersonData GetPerson();
    }
}

Basically, my interface has one function that returns an object of type PersonData. 基本上,我的接口有一个函数返回一个PersonData类型的对象。

I want to distribute these two files to my clients, so they can code their DLLs based on these. 我想将这两个文件分发给我的客户端,以便他们可以基于这些文件对DLL进行编码。 So one client would create a DLL which returns a PersonData object, with nationality set to "American", and another would return a PersonData object with nationality set to Japanese. 因此,一个客户端将创建一个DLL,该DLL返回一个国籍设置为“美国”的PersonData对象,而另一个客户端将返回一个国籍设置为日语的PersonData对象。 For instance, a DLL would look like this: 例如,DLL将如下所示:

namespace CreateAmerican
{
    public class CreateAmerican : CommonStuff.IPerson
    {
        public CommonStuff.Common.PersonData GetPerson()
        {
            CommonStuff.Common.PersonData person = new CommonStuff.Common.PersonData();
            person.Name = "Jennifer";
            person.Age = 23;
            person.Nationality = "American";
            return person;
        }
    }
}

Then, in my Main program, I want to read those DLLs - which I've put in a folder in advance - at runtime, and get the object returned by GetPerson() in each DLL. 然后,在我的主程序中,我想在运行时读取那些DLL(已预先放入文件夹中),并获取每个DLL中GetPerson()返回的对象。 That means, I want to have the same two IPerson.cs and Common.cs files included in my Main program, then create an object of type PersonData, and get the return value of GetPerson() method into it, and then do some work with it. 这意味着,我想在主程序中包含相同的两个IPerson.cs和Common.cs文件,然后创建一个PersonData类型的对象,并获取其中的GetPerson()方法的返回值,然后执行一些工作用它。 My main looks like this: 我的主要样子是这样的:

static void Main(string[] args)
{
    List<object> dllResultList = null;
    LoadDllClassesToList(Directory.GetCurrentDirectory(), out dllResultList);

    foreach(object item in dllResultList)
    {
        CommonStuff.Common.PersonData person = (CommonStuff.Common.PersonData)item;
        Console.WriteLine(String.Format("Name : {0}, Age : {1}, Nationality : {2}", person.Name, person.Age, person.Nationality));
    }
    Console.ReadLine();
}

The LoadDllClassesToList() method reads the DLLs at runtime, and put the return value of GetPerson() method into a list of "object" type. LoadDllClassesToList()方法在运行时读取DLL,并将GetPerson()方法的返回值放入“对象”类型的列表中。

When I run the program, everything works fine until I reach the line: 当我运行程序时,一切正常,直到到达该行:

CommonStuff.Common.PersonData person = (CommonStuff.Common.PersonData)item;

There, it throws an exception as follows: 在那里,它引发如下异常:

An unhandled exception of type 'System.InvalidCastException' occurred in MainProgram.exe MainProgram.exe中发生了类型为'System.InvalidCastException'的未处理异常

From what I understand, even though I have the same data type PersonData in my main program, the program sees it as something different to the PersonData object that my DLL returns. 据我了解,即使我的主程序中的数据类型为PersonData,程序也会将其视为与DLL返回的PersonData对象不同的东西。

So here's my question; 所以这是我的问题; how would I use an interface like IPerson, and a common data type such as PersonData, which both my DLLs and main program can share? 我将如何使用IPerson等接口以及DLL和主程序可以共享的通用数据类型(如PersonData)? My actual program has more complex data types, so I can't return something like an array of standard data types. 我的实际程序具有更复杂的数据类型,因此我无法返回类似标准数据类型的数组。 I need to be able to return a user-defined data type like PersonData. 我需要能够返回用户定义的数据类型,例如PersonData。

Thanks in advance! 提前致谢!

Provide assembly instead of source for shared classes and interfaces. 提供程序集而不是源代码来共享类和接口。 Clients and you will link to the same assembly and code will work fine. 客户和您将链接到相同的程序集,并且代码可以正常工作。

Alternatively you can give up type safety and use reflection or dynamic to use client's objects. 或者,您可以放弃类型安全性,而使用反射或动态使用客户端的对象。

The best option would be to set your interfaces in separated library, which could have been used by Clients. 最好的选择是将interfaces设置在单独的库中,客户端可能已经使用过。

If sharing of your assembly is impossible because of any reasons, I'm affraid the only option is using of dynamic type or reflection . 如果由于某种原因无法共享程序集,那么我唯一的选择是使用dynamic类型或reflection

dynamic person = item;

Same structure of class or interface like in 3rd party DLL is still different class or interface, as long as those classes/interfaces coming from different assembly. 与第三方DLL中相同的类或接口结构,仍然是不同的类或接口,只要这些类/接口来自不同的程序集即可。

You may like to give a try to AutoMapper which could later translate type to your local one. 您可能想尝试一下AutoMapper ,以后可以将类型转换为本地类型。 here 这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM