2012-10-17 24 views
6

我有一个类型项目,我定义自定义类对象,我想在我的主应用程序中工作。这些对象基本上是从字符串派生出来的,并被解析成一个结构体如何支持多种自定义类型?

我有两个问题

1 - 在一个单独的项目,我有一个文件读取器类,我扫描的文本文件我已经定义字符串类型。例如通过正则表达式。目前,我将我的类型项目添加为项目引用,并且只在正常阅读类的顶部列出正则表达式。当我找到一个类型,我将字符串转换为适当的类型。然而,我怎么能改善这个,这是它直接连接到我的类型项目 - 所以当我用新类型更新它的Read类知道它应该支持新类型?

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

任何意见非常感谢。

编辑:加什么I''m试图做的示例代码

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

} 

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

// TYPE 2

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

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

// PROJECT 3

class DoSomethingToTypeObject{ 

//detect type and call appropriate function to process 

} 

// PROJECT 4 - MAIN PROJECT与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); 
      } 
     } 
    } 
} 

回答

1

我希望我能正确理解你。

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

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

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的保持缓和发现过程。 使用泛型接口将允许保持您的代码类型安全(而不是使用类型对象的值),但在恢复对象时必须添加一些逻辑才能正确访问您的值。

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

编辑:基于新的信息

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

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

所以这就是我要做的: 我会将转换逻辑正确地移动到Type类中,polymophism将负责确切地调用哪个转换。

我会把RegularExpression用来检测Type到Type本身,这将允许你使用反射和Factory类更容易地讨论。

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

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)); 
+0

我会试试这个。我用我想要做的事情的示例代码更新了我的原始帖子。请看看它是否会改变您的任何建议。我不确定这个**字符串FoundItem {get;组; } string Expression {get; }'**在界面中。什么是Founditem和表达式(匹配和正则表达式?)。对我来说,当我找到它的时候,它是一个字符串,但稍后它会转换为数据结构。这很重要吗? – sjs

+0

FoundItem和Expression只是在接口中的成员的例子,并不一定要在那里。 我在看你提供的代码,你只是使用基于类型的特定转换的结果,还是你需要使用这个结构,因为它以后呢? –

+0

我的DoSomethingClass会修改对象内部的字符串。例如,说我的字符串对象表示一个CSV文件中的一行。也许我需要用特定值替换第三列。在这种情况下,我需要返回相同的结构,以便写入函数可以访问组成该行的所有值。 DoSomthing的每个实现(每个类型)将保持结构完整。我可能有其他模式(DoSomething2)使用该对象,但执行不同的功能,如检索值。只有Write类将输出一个字符串,因为它最初是在文件中。 – sjs

6

您应该使用一个接口,然后让所有类型实现接口。做完这些之后,你应该改变你的Read类来在接口上运行而不是单独的类。

通过这种方式,您可以添加尽可能多的类型,而无需更新Read类。

+1

如果你知道时间提前哪种类型你期待下一个读这只会工作。 –

+0

你确定吗?只要他使用他现在使用的接口和他的类,并在将来添加接口的实现? – mattytommo

+1

实现必须知道所有类型的检测目的。这对我来说似乎没有太多的SRP。虽然,我想你可以用某种工厂对象注册实现接口的类型。 –