Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.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# 如何基于项目中的类生成枚举变量_C#_Reflection_Enums_Attributes - Fatal编程技术网

C# 如何基于项目中的类生成枚举变量

C# 如何基于项目中的类生成枚举变量,c#,reflection,enums,attributes,C#,Reflection,Enums,Attributes,我正在编写一个DLL,它将公开如下方法: public static void Convert(string inputFile, string outputFile, FileType fileType) public enum FileType { ConvertClassOne, ConvertClassTwo, ConvertClassThree } 目前,FileType是一个枚举,如下所示: public static void Convert(stri

我正在编写一个DLL,它将公开如下方法:

public static void Convert(string inputFile, string outputFile, FileType fileType)
public enum FileType
{ 
    ConvertClassOne,
    ConvertClassTwo,
    ConvertClassThree
}
目前,FileType是一个枚举,如下所示:

public static void Convert(string inputFile, string outputFile, FileType fileType)
public enum FileType
{ 
    ConvertClassOne,
    ConvertClassTwo,
    ConvertClassThree
}
这将表示可以转换给定类型文件的每个类。我将有几个基于接口的不同类,每个类都可以处理特定类型的文件

我想公开一个枚举,它根据项目中具有给定属性的类自动更改自己,而不是像上面那样,每次添加类时都必须手动更改它,以便调用程序可以告诉我它们提供的文件类型

因此,如果我添加一个具有给定属性的类:

[SomeAttribute]
public class NewClassAdded()
{
}
文件类型枚举将获取此信息,调用程序将能够看到

FileType.NewClassAdded
不用我手工改变任何东西。我非常确定反射将允许我编写一个方法,返回具有给定属性的每个类的名称,但我不确定具体如何,也不知道如何将这些名称公开为枚举

谢谢


Andrew

这可能不是你想要的答案,但是你考虑过使用泛型吗?它将解决您可以添加新功能的问题。可以使用表示枚举的接口。对于每个枚举值,将有一个实现该接口的类。无论何时,只要添加一个新选项,就可以添加一个实现接口的新类。您可以在这些类中添加其他功能,也可以将它们用作枚举值的替代品(下面代码中的变量1和变量2)。例如:

class Program
{
    static void Main(string[] args)
    {
        Converter.Convert("input", "output", new FormatA());
        Converter.Convert("input", "output", new FormatB());
    }
}

class Converter
{
    public static void Convert<T>(string inputFile, string outputFile, T formatter) where T : IConvertFormat
    {
        // First variant: Keep the functionality in the formatter object

        formatter.DoSomething(inputFile, outputFile);

        // Second variant: check for the actual type

        if (formatter is FormatA)
        {
            // ... do format A
        }
        else if (formatter is FormatB)
        {
            // ... do format B
        }
    }
}

interface IConvertFormat
{
    // Method not required for variant 2
    void DoSomething(string inputFile, string outputFile);
}

class FormatA : IConvertFormat
{
    public void DoSomething(string inputFile, string outputFile)
    {
        // .. do it like Format A (not required for variant 2)
    }
}

class FormatB : IConvertFormat
{
    public void DoSomething(string inputFile, string outputFile)
    {
        // do it like Format B (not required for variant 2)
    }
}
类程序
{
静态void Main(字符串[]参数)
{
Convert.Convert(“输入”,“输出”,newformata());
Convert.Convert(“输入”,“输出”,新格式b());
}
}
类转换器
{
公共静态无效转换(字符串输入文件、字符串输出文件、T格式化程序),其中T:IConvertFormat
{
//第一个变体:将功能保留在formatter对象中
格式化程序.DoSomething(输入文件,输出文件);
//第二种变体:检查实际类型
if(格式化程序是FormatA)
{
//…做格式化
}
else if(格式化程序为FormatB)
{
//…做格式B
}
}
}
接口IConvertFormat
{
//变量2不需要方法
void DoSomething(字符串输入文件、字符串输出文件);
}
类FormatA:IConvertFormat
{
公共void DoSomething(字符串输入文件、字符串输出文件)
{
//…按照格式A进行操作(变体2不需要)
}
}
类FormatB:IConvertFormat
{
公共void DoSomething(字符串输入文件、字符串输出文件)
{
//按格式B执行(变体2不需要)
}
}

注:我认为这基本上就是@Jauch的建议。

根据讨论,我将给你以下想法,@Starfleet。 首先,创建一个带有“转换”函数和“描述”属性的接口

interface IFileConversion
{
    bool Convert (string inputFile, string outputFile);
    string Description { get; }
}
将此接口放在dll上,任何想要实现它的类都可以引用它

然后,您可以在您拥有的任何“FileType”类上实现该接口。 在您的库中,您可以创建一个函数来返回实现IFileConversion的所有类(通过反射非常简单)

比如:

static class Info
{
    public static List<IFileConversion> AvailableConversions ()
    {
       //Code to retrieve the available classes that implement IFileConversion
    }
}
只需输入“FileConversion.”并遍历将出现的列表(包含您提供的额外信息),就可以很容易地看到可用的列表

使用IFileConversion接口的优点是,您的合作伙伴(其他开发人员)不必担心该类的任何已知信息。他们只是选择了他们想要的(通过描述或文档)并调用转换例程


在任何情况下,这两种解决方案都比枚举描述符更好,更具描述性。

您几乎肯定无法通过反射来实现这一点,因为根据定义,到那时代码必须已经编译好。要做到这一点,您需要某种预构建过程,类似于AOP实现所做的。正如@Servy所说,您的“转换”例程必须事先知道每种文件类型类,才能在开关或if/else if块中使用枚举。因此,这种方法肯定不会“那么”有用(即使你想做你想做的事情,我认为这是不可能的(或很容易的),即使使用reflaction。为什么不使用一个接口来处理“转换”并使每个文件类型类实现它,所以你的“转换”例程不必担心细节?为什么不创建一个T4模板呢?查看这篇文章@Jauch,这不是问题。他正在编写一个类库。当他将代码添加到库中时,他希望它自动添加到枚举中。他的库的使用者将使用一个已经构建的库,其中包含所有实现w在编写代码时。我的理解是,库的使用者并没有添加他们自己的转换器。哦,我明白了,@Servy。在这种情况下,我不认为这样做的效用是为了付出这样的努力。无论如何,假设目标是“定义”正确的转换方法,通过使用枚举,我认为最好使用接口,或者使用带有一些虚拟方法的基类,使代码通用,并且与文件类型的不同实现的数量无关。大致上,@Izydrmr。有其他方法,但我发现了一个优雅的方法。但是调用程序必须知道“FormatA”和“FormatB”的存在?枚举的全部原因是,它们显示所有选项,而不必知道要传递的实际类名。我不确定“调用程序必须知道”是什么意思。你是说,程序员知道,还是说程序可以查询选项,例如,向用户显示选项?你确实知道