如何支持多种自定义类型?

sjs*_*sjs 6 c#

我有一个Types项目,我在其中定义了我想在我的主应用程序中处理的自定义类对象.对象基本上是从字符串派生并解析成结构的.

我有两个问题

1 - 在一个单独的项目中,我有一个文件阅读器类,我在其中扫描文本文件以查找我定义的字符串类型.例如通过正则表达式.目前我添加了我的Types项目作为项目引用,我只列出了我读类顶部的正则表达式.当我找到一个类型我将字符串转换为适当的类型.但是,我如何才能改进这一点,以便它直接连接到我的Types项目 - 所以当我用新类型更新它时,Read类知道它应该支持新类型?

2 - 我正在尝试创建一个在从文本文件中读取后对这些特定类型起作用的DLL.如何告诉我的DLL我想支持我的Types项目中的类型?我是否必须为我想要处理的每种类型创建一个重载函数?我使用界面吗?

任何意见是极大的赞赏.

编辑:添加了我正在尝试做的示例代码

// PROJECT 1 - 处理IO操作,如读取和写入
//读取类作业中的函数是通过正则表达式找到几种预定义字符串类型之一...一旦发现它们被转换为数据结构(通过将字符串传递给构造函数)在另一个项目中定义的类型类

 public class Read
{
    public string[] FileList { get; set; }

    private static Int64 endOffset = 0;
    private FileStream readStream;
    private StreamReader sr;

    private System.Text.RegularExpressions.Regex type1 = new System.Text.RegularExpressions.Regex(@"@123:test");
    private System.Text.RegularExpressions.Regex type2 = new System.Text.RegularExpressions.Regex(@"TESTTYPE2");

    public Read(string[] fl)
    {
        FileList = fl;
    }

    public object ReturnMessage(FileStream readStream, out int x)
    {
        //readStream = new FileStream(file, FileMode.Open, FileAccess.Read);
        x = 0;
        //endOffset = 0;
        bool found = false;
        char ch;
        string line = string.Empty;

        object message = null;

        while (!(x < 0)) //do this while not end of line (x = -1)
        {
            readStream.Position = endOffset;

            //line reader
            while (found == false)  //keep reading characters until end of line found
            {
                x = readStream.ReadByte();
                if (x < 0)
                {
                    found = true;
                    break;
                }
                // else if ((x == 10) || (x == 13))
                if ((x == 10) || (x == 13))
                {
                    ch = System.Convert.ToChar(x);
                    line = line + ch;
                    x = readStream.ReadByte();
                    if ((x == 10) || (x == 13))
                    {
                        ch = System.Convert.ToChar(x);
                        line = line + ch;
                        found = true;
                    }
                    else
                    {
                        if (x != 10 && (x != 13))
                        {
                            readStream.Position--;
                        }
                        found = true;
                    }
                }
                else
                {
                    ch = System.Convert.ToChar(x);
                    line = line + ch;
                }
            }//while - end line reader 



            //examine line (is it one of the supported types?)
            if (type1.IsMatch(line))
            {
                message = line;
                endOffset = readStream.Position;

                break;
            }
            else
            {
                endOffset = readStream.Position;
                found = false;
                line = string.Empty;
            }

        }//while not end of line


        return message;
    }

}
Run Code Online (Sandbox Code Playgroud)

// PROJECT 2 - 包含定义类型的类

// TYPE1

namespace MessageTypes.Type1
{
public sealed class Type1
{
    public List<Part> S2 { get; set; }

    public Type1(string s)
    {
        S2 = new List<Part>();
        string[] parts = s.Split(':');
        for (int i = 0; i < parts.Length; i++)
        {
            S2.Add(new Part(parts[i]));
        }
    }
}

public sealed class Part
{
    public string P { get; set; }

    public Part(string s)
    {
        P = s;
    }
}
}
Run Code Online (Sandbox Code Playgroud)

// TYPE 2

namespace MessageTypes.Type2
{
public sealed class FullString
{
    public string FS { get; set; }

    public FullString(string s)
    {
        FS = s;
    }
}
}
Run Code Online (Sandbox Code Playgroud)

//项目3

class DoSomethingToTypeObject{

//detect type and call appropriate function to process

} 
Run Code Online (Sandbox Code Playgroud)

//项目4 - 带GUI的主项目

    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        if (tabControl1.SelectedIndex == 0) //Processing Mode 1
        {
            //load file list from main window - Mode1 tab
            IOHandler.Read read = new IOHandler.Read(new string[2] { @"C:\file1.txt", @"C:\file2.txt" });

            //read files
            foreach (string file in read.FileList)
            {

                //while not end of stream
                myobject = read.ProcessFile(file);

                DoSomethingtoTypeObject DS = new DoSomethingtoTypeObject(myobject);

                //write transoformed object
                write(myobject);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

mat*_*mmo 6

您应该使用接口,然后使所有类型实现接口.完成后,您应该更改Read类以在接口上操作而不是单个类.

这样,您可以根据需要添加任意数量的类型,而不必更新Read类.


Yan*_*net 1

我希望我能正确理解你。

\n\n

您在 Type 项目中创建的类代表一些具有不同行为但具有相同数据成员的对象,您希望能够在项目中轻松使用这些对象,而不必显式列出这些对象。

\n\n

我将创建一些基本接口,Types 项目中的所有对象都将实现该接口。\n然后我将使用一个工厂类,该类将使用反射来收集实现所述接口的所有对象。

\n\n
public interface iFoo\n{\n    string FoundItem { get; set; }\n    string Expression { get; }\n    string Value { get; set; }\n    void sharedFunctionName();\n}\n\npublic static class FooFactory\n{\n    public static List<iFoo> GetTypeList()\n    {\n        List<iFoo> types = new List<iFoo>();\n        types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()\n                       from t in assembly.GetTypes()\n                       where t.IsClass && t.GetInterfaces().Contains(typeof(iFoo))\n                       select Activator.CreateInstance(t) as iFoo);\n\n        return types;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,您的读者将收到受支持类型的所有必要信息,而无需您再手动指定。

\n\n

由于我猜测值类型在某些时候会有所不同,因此您可以使用如下通用接口:

\n\n
public interface iFoo\n{\n    string FoundItem { get; set; }\n    string Expression { get; }\n    void sharedFunctionName();\n}\n\npublic interface iFoo<T> : iFoo\n{\n    T Value { get; set; }\n}\n\npublic static class FooFactory\n{\n    public static List<iFoo> GetTypeList()\n    {\n        List<iFoo> types = new List<iFoo>();\n        types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()\n                       from t in assembly.GetTypes()\n                       where t.IsClass && t.GetInterfaces().Contains(typeof(iFoo))\n                       select Activator.CreateInstance(t) as iFoo);\n\n        return types;\n    }\n}\n\npublic class FooBar : iFoo<int>\n{\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在此示例中,保留基本接口 iFoo 以简化发现过程。\n使用通用接口将允许保持代码类型安全(而不是使用类型对象的值),但在恢复对象时必须添加一些逻辑能够正确访问您的价值。

\n\n

另外,如果您需要创建需要在所有对象中共享的函数,您可以在工厂类和 Voil\xc3\xa0 中添加扩展方法。

\n\n

编辑:

\n\n

根据新信息:

\n\n

您的类型对应于您将在基于某些正则表达式的文件中找到的数据类型。\n根据用户选择和类型,可能会有不同类型的转换。

\n\n

我们知道用户必须从列表中选择一种模式,这将影响应用于类型的转换。

\n\n

所以这就是我要做的:\n我会将转换逻辑直接移到 Type 类中,多态性将准确处理将调用哪个转换。

\n\n

我会将用于检测类型的正则表达式放入类型本身中,这将允许您更轻松地使用反射和前面讨论的工厂类。

\n\n

这样,一切都是标准的。您的读者无需手动干预即可了解您在类型项目中创建的任何新类型,并且一旦检测到就可以应用正确的转换,并且始终可以访问原始字符串。

\n\n
public enum UserMode {Mode1, Mode2};\n\npublic interface iType\n{\n   string Expression {get;}\n   string OriginalString {get; set;}\n   string Transform(UserMode Mode);\n   iType getNewInstance(string OriginalString);\n\n}\n\npublic class Type1 : iType\n{\n   public string Expression {get { return "RegularExpression"; }}\n   public string OriginalString {get; set;}\n   //Add any other private members you need to accomplish your work here.\n   public string Transform(UserMode Mode)\n   {\n      switch(Mode)\n      {\n         case UserMode.Mode1:\n             //write the transformation code for this scenario\n             return ResultString;\n             break;\n      }\n   }\n\n   public iType getNewInstance(string Original)\n   {\n     return (iType)(new Type1(){ OriginalString = Original });\n   }\n}\n\npublic static class TypeFactory\n{\n   public static List<iType> GetTypeList()\n   {\n       List<iType> types = new List<iType>();\n       types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()\n                      from t in assembly.GetTypes()\n                      where t.IsClass && t.GetInterfaces().Contains(typeof(iType))\n                      select Activator.CreateInstance(t) as iType);\n\n       return types;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,如果匹配列表中 iType 中的表达式,您所要做的就是。\n当您匹配时,您需要执行以下操作:

\n\n
var TransformationReady = from t in TypeFactory.GetTypeList()\n                          where Regex.IsMatch(YourFileLine, t.Expression)\n                          select t.getNewInstance(Regex.Match(YourFileLine, t.Expression));\n
Run Code Online (Sandbox Code Playgroud)\n