6

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

我有两个问题

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

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

任何意见是极大的赞赏。

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

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

 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;
    }

}

//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;
    }
}
}

//类型2

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

    public FullString(string s)
    {
        FS = s;
    }
}
}

//项目 3

class DoSomethingToTypeObject{

//detect type and call appropriate function to process

} 

//项目 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);
            }
        }
    }
}
4

2 回答 2

6

您应该使用接口,然后让所有类型都实现该接口。之后,您应该更改您的 Read 类以在接口而不是单个类上操作。

这样,您可以添加任意数量的类型,而不必更新 Read 类。

于 2012-10-17T20:44:57.270 回答
1

我希望我能正确理解你。

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

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

public interface iFoo
{
    string FoundItem { get; set; }
    string Expression { get; }
    string Value { get; set; }
    void sharedFunctionName();
}

public static class FooFactory
{
    public static List<iFoo> GetTypeList()
    {
        List<iFoo> types = new List<iFoo>();
        types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()
                       from t in assembly.GetTypes()
                       where t.IsClass && t.GetInterfaces().Contains(typeof(iFoo))
                       select Activator.CreateInstance(t) as iFoo);

        return types;
    }
}

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

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

public interface iFoo
{
    string FoundItem { get; set; }
    string Expression { get; }
    void sharedFunctionName();
}

public interface iFoo<T> : iFoo
{
    T Value { get; set; }
}

public static class FooFactory
{
    public static List<iFoo> GetTypeList()
    {
        List<iFoo> types = new List<iFoo>();
        types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()
                       from t in assembly.GetTypes()
                       where t.IsClass && t.GetInterfaces().Contains(typeof(iFoo))
                       select Activator.CreateInstance(t) as iFoo);

        return types;
    }
}

public class FooBar : iFoo<int>
{

}

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

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

编辑:

根据新信息:

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

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

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

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

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

public enum UserMode {Mode1, Mode2};

public interface iType
{
   string Expression {get;}
   string OriginalString {get; set;}
   string Transform(UserMode Mode);
   iType getNewInstance(string OriginalString);

}

public class Type1 : iType
{
   public string Expression {get { return "RegularExpression"; }}
   public string OriginalString {get; set;}
   //Add any other private members you need to accomplish your work here.
   public string Transform(UserMode Mode)
   {
      switch(Mode)
      {
         case UserMode.Mode1:
             //write the transformation code for this scenario
             return ResultString;
             break;
      }
   }

   public iType getNewInstance(string Original)
   {
     return (iType)(new Type1(){ OriginalString = Original });
   }
}

public static class TypeFactory
{
   public static List<iType> GetTypeList()
   {
       List<iType> types = new List<iType>();
       types.AddRange(from assembly in AppDomain.CurrentDomain.GetAssemblies()
                      from t in assembly.GetTypes()
                      where t.IsClass && t.GetInterfaces().Contains(typeof(iType))
                      select Activator.CreateInstance(t) as iType);

       return types;
    }
}

现在,如果匹配列表中 iTypes 中的表达式,您将要做的一切。当你有比赛时,你会:

var TransformationReady = from t in TypeFactory.GetTypeList()
                          where Regex.IsMatch(YourFileLine, t.Expression)
                          select t.getNewInstance(Regex.Match(YourFileLine, t.Expression));
于 2012-10-18T01:08:43.290 回答