Преобразование значений между одной и той же структурой в другом пространстве имен. C # - PullRequest
3 голосов
/ 31 марта 2011

У меня есть две похожие [все атрибуты одинаковые.] Структуры в разных пространствах имен.

Теперь, когда я пытаюсь скопировать значения между объектами этих структур, я получаю ошибки.

Как я могу сделать возможным копирование значений между объектами двух одинаковых структур, находящихся в разных пространствах имен?

Заранее спасибо.

С уважением,

John

Ответы [ 7 ]

5 голосов
/ 03 декабря 2011

Я столкнулся с этой же проблемой при использовании нескольких веб-сервисов от внешнего поставщика через WCF. Существует очень большое дерево вложенных объектов, которое просто болезненно для отображения между классами, тем более что в этом дереве есть несколько экземпляров для хранения абстрактного базового класса в качестве члена. Поскольку все эти классы определены с атрибутами XML-сериализации, необходимыми для передачи в веб-службу, я решил использовать сериализатор, чтобы выполнить преобразование для меня.

    TOutput ConvertEquivalentTypes<TInput, TOutput>(TInput structure)
        where TInput : class
        where TOutput : class
    {
        TOutput result = null;

        using (Stream data = new MemoryStream())
        {
            new XmlSerializer(typeof(TInput)).Serialize(data, structure);
            data.Seek(0, SeekOrigin.Begin);
            result = (TOutput)new XmlSerializer(typeof(TOutput)).Deserialize(data);
        }

        return result;
    }
5 голосов
/ 31 марта 2011

Вы не можете, автоматически, просто используя встроенные преобразования каркаса.

Короткие имена (т. Е. В пространстве имен) здесь совершенно не имеют значения - для CLR A.B.C.SomeTypeи A.B.C1.SomeType отличаются от X.Y.Foo и A.B.Bar.

. Вы должны либо написать свои собственные процедуры преобразования, либо (предпочтительно) избегать использования двух разных типов во-первых, если они делают то же самоевещь.В качестве альтернативы вы могли бы использовать подход, основанный на отражении, чтобы выполнить преобразование ... но это все еще не заставляет время выполнения сделать это.

5 голосов
/ 31 марта 2011

Использование AutoMapper .

Mapper.CreateMap<My.NS1.Structure, My.NS2.Structure>();
My.NS1.Structure struct1;
My.NS2.Structure struct2 = (My.NS2.Structure) Mapper.Map(struct1);
2 голосов
/ 10 сентября 2013

Альтернатива ответу Чака Гая - вы можете использовать отражение, чтобы получить и установить значения. Понятия не имею, какие преимущества / недостатки производительности.

public static class EquivelantStructureConversion<TInput, TOutput>
    where TInput : class
    where TOutput : new()
{
    public static TOutput Convert(TInput input)
    {
        var output = new TOutput();

        foreach (var inputProperty in input.GetType().GetProperties())
        {
            var outputProperty = output.GetType().GetProperty(inputProperty.Name);
            if (outputProperty != null)
            {
                var inputValue = inputProperty.GetValue(input, null);
                outputProperty.SetValue(output, inputValue, null);
            }
        }

        return output;
    }
}

Приведенный выше пример не вызовет исключения, если свойство типа вывода не существует, но вы можете легко добавить его.

0 голосов
/ 01 апреля 2011

Вы можете использовать союз:

public struct A
{
    int x, y;
    double a, b;

    public A(int x, int y, double a, double b)
    {
        this.x = x;
        this.y = y;
        this.a = a;
        this.b = b;
    }
}
public struct B
{
    int x, y;
    double a, b;
}

[StructLayout(LayoutKind.Explicit)]
public class Union
{
    [FieldOffset(0)]
    public A a;
    [FieldOffset(0)]
    public B b;

    public Union(A a)
    {
        this.b = default(B);
        this.a = a;            
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new A(5, 10, 0.25, 0.75);
        Union union = new Union(a);
        B b = union.b; //contains 5,10,0.25,0.75
    }
}
0 голосов
/ 31 марта 2011

поскольку все атрибуты одинаковы, вы можете, например, определите интерфейс, опишите вашу структуру и внедрите этот интерфейс в свои структуры. Затем приведите ваши структуры к интерфейсу для копирования значений.

С уважением, O

0 голосов
/ 31 марта 2011

Из описания в вопросе звучит так, как будто вы хотите иметь неявное преобразование между вашими типами.Хотя вы можете сделать это, и в дополнение к другим предложениям, вам лучше использовать другие методы, такие как

  • с классом для преобразования для вас
  • добавляяконструктор для каждого класса, чтобы сгенерировать тип A из типа B и наоборот
  • , добавив в каждый метод расширения, чтобы он действовал как фабрика для создания другого
...