6

メイン アプリケーションで作業するカスタム クラス オブジェクトを定義するタイプ プロジェクトがあります。オブジェクトは基本的に文字列から派生し、構造に解析されます。

2つの問題があります

1 - 別のプロジェクトに、定義した文字列型のテキスト ファイルをスキャンするファイル リーダー クラスがあります。たとえば、正規表現で。現在、タイプ プロジェクトをプロジェクト参照として追加し、読み取りクラスの先頭に正規表現をリストするだけです。型が見つかったら、文字列を適切な型に変換します。ただし、これを改善して、Types プロジェクトに直接接続するにはどうすればよいですか?新しい型で更新すると、Read クラスは新しい型をサポートする必要があることを認識しますか?

2 - テキスト ファイルから読み取られた後、これらの特定の型で動作する DLL を作成しようとしています。タイプ プロジェクトでタイプをサポートしたいことを DLL に伝えるにはどうすればよいですか? 作業したい型ごとにオーバーロードされた関数を作成する必要がありますか? インターフェイスを使用しますか?

どんなアドバイスでも大歓迎です。

編集:私がやろうとしていることのサンプルコードを追加しました

//PROJECT 1 - 読み取りと書き込みのような IO 操作を処理
します //読み取りクラスの関数の仕事は、正規表現によっていくつかの事前定義された文字列型の 1 つを見つけることです...それらがデータ構造に変換されると、(文字列をコンストラクターに渡すことによって)他のプロジェクトで定義された型クラス

 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 が保持されます。ジェネリック インターフェイスを使用すると、(型オブジェクトの値を使用するのではなく) コードの型を安全に保つことができますが、値に適切にアクセスできるようにするには、オブジェクトを回復するときにいくつかのロジックを追加する必要があります。

さらに、すべてのオブジェクト内で共有する必要がある関数を作成する必要がある場合は、ファクトリ クラス内に拡張メソッドを追加することができます。

編集:

新しい情報に基づいて:

タイプは、正規表現に基づいてファイル内にあるデータのタイプに対応します。ユーザーの選択とタイプに基づいて、異なるタイプの変換が存在する場合があります。

ユーザーはリストからモードを選択する必要があり、これはタイプに適用する変換に影響します。

これが私がすることです: 変換ロジックを Type クラスに移動します。ポリモフィズムは、どの変換が呼び出されるかを正確に処理します。

Type を検出するために使用する RegularExpression を 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;
    }
}

これで、リスト内の iType の式と一致する場合に必要な作業はすべて完了です。試合があるときは、次のことを行います。

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 に答える