0

質問をより具体的にし、実際の関心領域を対象とするように言い換えています。

私は自分のエンティティである多くの異なるクラスを持っていますが、そのクラスにあるものは知りません。エンティティを新しいものにアップグレードしたいときは、プロパティを同じ名前の新しいものに転送したいと思います (私が知っているように、それらは大文字と小文字を区別しません)。

私の問題は単純ですが、おそらく複雑な答えが必要です。

アップグレードされたものとは異なるタイプに遭遇した場合、古いものを新しいものにキャストする必要があります。それがポイントなので、両方のタイプは不明です。必要な 2 つのクラスを渡すことができ、プロパティが正常に転送されます。

したがって、2つのクラスがある場合:

public class OldEntity
{
    public string Name {get;set;}
    public int SomeProperty {get;set;}
}

public class NewEntity
{
    public string Name {get;set;}
    public string SomeProperty {get;set;}
}

そのため、古いタイプの を見つけてSomeProperty、それを新しいタイプの にキャストする必要がありSomePropertyます。

私ができると思ったこと、そしてそれを行うためのより一般的な方法があることを願っています:

switch (typeof(SomeProperty.Value.GetType())
{
    case typeof(Int):
        return Int.Parse(OldSomeProperty.Value);
}

明らかにそれは非常に生のコードですが、要点はわかります。

誰かがそれを行うためのより一般的な方法を教えてください.AutoMapperをダウンロードしたことはもう1つあります.

だから私は単純な回避策を試みましたが、あまり一般的ではありません:

public static object ConvertSourceObjectDestinationObject(object source, object destination)
{
    // get the string representation of the source object
    var strRepresentation = source.ToString();
    // find out the destinations type
    var originalCode = AssemblyCode(destination.GetType().Assembly.ToString());

    // search for a match then convert the source object to the new destination objects type
    switch (originalCode)
    {
        case 0:
            return strRepresentation;
        case 1:
            return int.Parse(strRepresentation);
        case 2:
            return decimal.Parse(strRepresentation);
        case 3:
            return DateTime.Parse(strRepresentation);
        case 4:
            return byte.Parse(strRepresentation);
        case 5:
            return float.Parse(strRepresentation);
        case 6:
            return Guid.Parse(strRepresentation);
        default:
            return strRepresentation;
    }
}

public static int AssemblyCode(string assemblyString)
{
    if (assemblyString.Equals(typeof(string).Assembly.ToString()))
        return 0;

    if (assemblyString.Equals(typeof(int).Assembly.ToString()))
        return 1;

    if (assemblyString.Equals(typeof(decimal).Assembly.ToString()))
        return 2;

    if (assemblyString.Equals(typeof(DateTime).Assembly.ToString()))
        return 3;

    if (assemblyString.Equals(typeof(byte).Assembly.ToString()))
        return 4;

    if (assemblyString.Equals(typeof(float).Assembly.ToString()))
        return 5;

    if (assemblyString.Equals(typeof(Guid).Assembly.ToString()))
        return 6;

    return -1;
}

Parse の代わりに TryParse を実行してより安全にする新しいものを作成しましたが、要点はわかります。エレガントではないことはわかっていますが、未知のオブジェクトを他の未知のオブジェクトに適切にキャストする方法を誰かが教えてくれれば、それは素晴らしいことです。

4

2 に答える 2

1

ジェネリック システムは、ジェネリックがどのような型であるかを知る助けが必要な場合があります。これは、型制約 ( ref ) で処理されます。これは、例に役立つ場合があります。

キャストしたいジェネリック型が常に何らかの基本クラスであることがわかっている場合は、where T:<base class name>制約を使用します。

キャスト例外が、継承されていない型間の暗黙的なキャストを認識していないことが原因である場合、リフレクションが唯一のオプションである可能性があります。

于 2013-01-05T18:36:58.210 に答える
0

一般的な制約 new を使用します

 public static void SetEntityValue<TEntity>(ref TEntity entityToTransform, PropertyHelper entityProperty) where TEntity: new

これにより、次のことが可能になります。

TEntity ent = new TEntity()

または(そして、これがあなたが望むものだと思います)

同じこと(ジェネリック制約)を使用して、メソッドにジェネリックパラメーターの型が何であるか/派生したものを伝えることができます。

public static void SetEntityValue<TEntity>(ref TEntity entityToTransform, PropertyHelper entityProperty) where TEntity: x

これは基本的に、ジェネリック型がどうあるべきかをコンパイラに伝えることができることを意味します(つまり、メソッド内のキャストは意味があり、コンパイルされます

タイプが何になるかわからない場合は、オブジェクトでリフレクションを使用することに興味があるかもしれません...

于 2013-01-05T17:37:40.450 に答える