2012-10-17 39 views
6

Tôi có một dự án Loại nơi tôi xác định các đối tượng lớp tùy chỉnh mà tôi muốn làm việc trong ứng dụng chính của mình. Các đối tượng cơ bản có nguồn gốc từ chuỗi và phân tích cú pháp thành một cấu trúc.Làm cách nào để hỗ trợ nhiều loại tùy chỉnh?

Tôi có hai vấn đề

1 - Trong một dự án riêng biệt Tôi có một lớp người đọc tập tin nơi tôi quét tập tin văn bản cho các loại chuỗi Tôi đã xác định. Ví dụ bằng biểu thức chính quy. Hiện tại tôi đã thêm dự án Types của tôi làm tham chiếu dự án và tôi chỉ liệt kê các biểu thức chính quy ở đầu lớp đọc của mình. Khi tôi tìm thấy một loại tôi chuyển đổi chuỗi thành loại thích hợp. Tuy nhiên làm thế nào tôi có thể cải thiện điều này để nó được kết nối trực tiếp với dự án loại của tôi - vì vậy khi tôi cập nhật nó với các kiểu mới, lớp Read biết rằng nó sẽ hỗ trợ các kiểu mới?

2 - Tôi đang cố gắng tạo một DLL hoạt động trên các loại cụ thể sau khi chúng được đọc từ tệp văn bản. Làm thế nào để tôi nói với DLL của tôi rằng tôi muốn hỗ trợ các loại trong dự án loại của tôi? Tôi có phải thực hiện một chức năng quá tải cho từng loại tôi muốn làm việc không? Tôi có sử dụng giao diện không?

Bất kỳ lời khuyên nào được đánh giá cao.

EDIT: Thêm mã ví dụ về những gì I''m cố gắng làm

// DỰ ÁN 1 - xử lý hoạt động IO như Đọc và viết
// chức năng trong công việc lớp đọc là để tìm thấy một trong một số loại chuỗi được xác định trước bởi biểu thức chính quy ... một lần thấy họ được chuyển đổi thành các cấu trúc dữ liệu (bằng cách thông qua chuỗi để xây dựng các kiểu lớp được định nghĩa trong dự án khác

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

} 

// dỰ áN 2 - chứa các lớp mà xác định các loại

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

// DỰ ÁN 3

class DoSomethingToTypeObject{ 

//detect type and call appropriate function to process 

} 

// DỰ ÁN 4 - DỰ ÁN CHỦ với 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); 
      } 
     } 
    } 
} 

Trả lời

1

Tôi hy vọng tôi hiểu chính xác bạn.

Lớp bạn tạo trong dự án Loại đại diện cho một số đối tượng có hành vi khác nhau nhưng cùng một thành viên dữ liệu và bạn muốn có thể sử dụng chúng dễ dàng trong dự án của mình mà không cần phải liệt kê rõ ràng các đối tượng này.

Tôi sẽ tạo một số giao diện cơ sở mà tất cả các đối tượng của tôi trong dự án Loại sẽ triển khai. Sau đó tôi sẽ sử dụng một Lớp Nhà máy có thể sử dụng sự phản chiếu để thu thập tất cả các đối tượng thực hiện giao diện đã nói.

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

Sau đó, Reader của bạn sẽ nhận được tất cả thông tin cần thiết cho các loại được hỗ trợ mà bạn không phải đọc chính xác nó nữa.

Vì tôi đoán kiểu giá trị sẽ khác nhau tại một số điểm, bạn có thể sử dụng một giao diện chung như thế này:

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> 
{ 

} 

Trong ví dụ này giao diện cơ sở IFoo được giữ để giảm bớt quá trình khám phá. Sử dụng giao diện chung sẽ cho phép giữ mã của bạn Loại an toàn (trái ngược với việc sử dụng Giá trị kiểu đối tượng) nhưng bạn sẽ phải thêm một số logic khi khôi phục đối tượng để có thể truy cập vào Giá trị của bạn đúng cách.

Ngoài ra, nếu bạn cần tạo các hàm cần được chia sẻ trong tất cả các đối tượng, bạn có thể thêm các phương thức mở rộng trong Lớp Nhà máy và Voilà.

EDIT:

Dựa trên những thông tin mới:

loại của bạn tương ứng với một loại dữ liệu mà bạn sẽ tìm thấy trong một tập tin dựa trên một số biểu hiện thường xuyên. Có thể có loại chuyển đổi khác nhau dựa trên lựa chọn của người dùng và Loại.

Chúng tôi biết rằng người dùng sẽ phải chọn một chế độ từ danh sách và điều này sẽ ảnh hưởng đến việc chuyển đổi áp dụng trên các loại.

Vì vậy, đây là những gì tôi sẽ làm: Tôi sẽ di chuyển logic chuyển đổi ngay vào lớp Loại, polymophism sẽ chăm sóc chính xác mà chuyển đổi sẽ được gọi.

Tôi sẽ đặt RegularExpression để sử dụng để phát hiện Loại thành chính nó, điều này sẽ cho phép bạn sử dụng phản chiếu và lớp Nhà máy thảo luận sớm hơn dễ dàng hơn.

Bằng cách này, mọi thứ đều là tiêu chuẩn. Người đọc của bạn biết về bất kỳ loại mới nào bạn tạo trong dự án kiểu mà không có sự can thiệp thủ công và một khi đã phát hiện ra phép biến đổi phù hợp có thể được áp dụng và chuỗi gốc luôn có thể truy cập được.

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

Bây giờ, tất cả các bạn sẽ phải làm gì nếu phù hợp với biểu thức từ iTypes trong danh sách. Khi bạn có một trận đấu bạn làm:

var TransformationReady = from t in TypeFactory.GetTypeList() 
          where Regex.IsMatch(YourFileLine, t.Expression) 
          select t.getNewInstance(Regex.Match(YourFileLine, t.Expression)); 
+0

Tôi sẽ thử điều này. Tôi đã cập nhật bài đăng gốc của mình bằng mã ví dụ về những gì tôi đang cố gắng thực hiện. Hãy xem xét trong trường hợp nó thay đổi bất kỳ đề xuất của bạn. Tôi không chắc chắn về điều này ** 'chuỗi FoundItem {get; bộ; } Biểu thức chuỗi {get; } '** trong giao diện. những gì là founditem và biểu thức (các trận đấu và biểu thức chính quy?).đối với tôi nó là một chuỗi đầu tiên khi tôi tìm thấy nó nhưng nó được chuyển đổi thành cơ sở dữ liệu sau này. Điều này có quan trọng không? – sjs

+0

FoundItem và Expression chỉ là ví dụ về các thành viên trong giao diện và không cần phải ở đó. Tôi đang xem mã bạn đã cung cấp, bạn có đang sử dụng kết quả của một phép biến đổi cụ thể dựa trên loại hay bạn cần sử dụng cấu trúc này như sau này không? –

+0

DoSomethingClass của tôi sẽ sửa đổi chuỗi bên trong đối tượng. Ví dụ: đối tượng chuỗi của tôi đại diện cho một dòng từ tệp CSV. Có lẽ tôi cần phải thay thế cột thứ 3 với giá trị cụ thể. Trong trường hợp này, tôi cần trả về cùng một cấu trúc để chức năng ghi sẽ có quyền truy cập vào tất cả các giá trị tạo nên dòng. Mỗi lần thực hiện DoSomthing (mỗi loại) sẽ giữ nguyên cấu trúc. Tôi có thể có các chế độ khác (DoSomething2) sử dụng đối tượng nhưng thực hiện chức năng khác nhau như truy xuất giá trị. Chỉ có lớp Write sẽ xuất ra một chuỗi như ban đầu trong tập tin. – sjs

6

Bạn nên sử dụng một giao diện, sau đó làm cho tất cả các loại của bạn thực hiện giao diện. Sau khi làm điều đó, bạn nên thay đổi lớp Read của bạn để hoạt động trên giao diện KHÔNG phải các lớp riêng lẻ.

Bằng cách đó bạn có thể thêm bao nhiêu loại tùy ý và không phải cập nhật lớp Đọc.

+1

Điều này sẽ chỉ hoạt động nếu bạn biết trước thời gian bạn muốn đọc tiếp theo. –

+0

Bạn chắc chắn về điều đó? Miễn là anh ấy đang sử dụng giao diện và các lớp học của anh ấy mà anh ấy hiện có và thêm vào trong tương lai, hãy triển khai giao diện đó? – mattytommo

+1

Việc triển khai sẽ phải biết về tất cả các loại cho mục đích phát hiện. Điều đó dường như không có nhiều SRP với tôi. Mặc dù, tôi cho rằng bạn có thể đăng ký các loại thực hiện giao diện với một số loại đối tượng nhà máy. –

Các vấn đề liên quan