Свойство класса доступа передается как универсальный тип - PullRequest
1 голос
/ 28 июня 2011

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

    public class MyClass1 
    {

            public string MyProperty1 { get; set; }

            //These properties are shared in both classes
            public bool Result { get; set; }
            public string EngineErrorMessage { get; set; }

    }
    public class MyClass2 
    {

            public string MyProperty2 { get; set; }

            //These properties are shared in both classes
            public bool Result { get; set; }
            public string EngineErrorMessage { get; set; }

    }


//The method is used to serialize classes above, classes are passed as generic types
    public void Serialization<T>(ref T engine)
            {
                try
                {
                 //Do some work with passed class
                 }
                catch (Exception e)
                {

                   //If Exception occurs I would like to write values to passed class properties, how to do that?
                   Result = false;
                   EngineErrorMessage = e.Message;
                }
    }

Полный код метода

     public void Submit<T>(ref T engine)
        {
            try
            {

                var workingDir = Path.Combine(Settings.FileStoragePath, Helpers.GetRandomInt(9).ToString());



                Directory.CreateDirectory(workingDir);
                var inputFile = Path.Combine(workingDir, Settings.InFileName);
                var outputFile = Path.Combine(workingDir, Settings.OutFileName);
                var deleteFile = Path.Combine(workingDir, Settings.DelFileName);

                try
                {



                    using (var stream = new FileStream(inputFile, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        Serializer.Serialize(stream, engine);
                    }


                    CheckStatus(outputFile);


                    using (var stream = new FileStream(outputFile, FileMode.Open, FileAccess.Read, FileShare.None))
                    {
                        engine = Serializer.Deserialize<T>(stream);                        
                    }


                }
                finally
                {
                    File.Create(deleteFile).Dispose();
                }
            }
            catch (Exception e)
            {
                //ToDo: Not implemented yet.
/*               Result = false;
               ErrorMessage = e.Message;*/
            }
        }

Ответы [ 3 ]

3 голосов
/ 28 июня 2011

Объявите интерфейс, содержащий свойства Result и EngineErrorMessage. Теперь у вас есть два варианта:

  1. Добавьте ограничение к параметру типа сериализации, чтобы сериализовать могли только те типы, которые являются производными от интерфейса, упомянутого выше, или
  2. В вашем блоке catch попытайтесь привести engine к интерфейсу, указанному выше. Если приведение выполнено успешно, запишите значения свойства, иначе ничего не делайте.

Пример:

public interface ISerializationErrorWriter
{
    bool Result { set; get; }
    string EngineErrorMessage { set; get; }
}

public class MyClass1 : ISerializationErrorWriter
{
    public string MyProperty1 { get; set; }

    public bool Result { get; set; }
    public string EngineErrorMessage { get; set; }
}

public class MyClass2 : ISerializationErrorWriter
{
    public string MyProperty2 { get; set; }

    public bool Result { get; set; }
    public string EngineErrorMessage { get; set; }
}

// Option 1:
public void Serialization_1<T>(ref T engine) where T : ISerializationErrorWriter
{
    try
    {
        //Do some work with passed class
    }
    catch (Exception e)
    {
        engine.Result = false;
        engine.EngineErrorMessage = e.Message;
    }
}

// Option 2:
public void Serialization_2<T>(ref T engine)
{
    try
    {
        //Do some work with passed class
    }
    catch (Exception e)
    {
        var serializationErrorWriter = engine as ISerializationErrorWriter;
        if(serializationErrorWriter != null)
        {
            serializationErrorWriter.Result = false;
            serializationErrorWriter.EngineErrorMessage = e.Message;
        }
    }
}
2 голосов
/ 28 июня 2011

Вам нужно будет использовать отражение в какой-то момент, через typeof(T) (или, может быть, engine.GetType()).Если это частый путь кода, вы можете кэшировать какую-то стратегию для каждого типа, чтобы избежать лишних затрат.Или, может быть, лучше: используйте предварительно созданный API сериализации, который оптимизирует для этого типа сценария (т.е. большинство из них).

Если вы имеете в виду Result и EngineErrorMessage, то 2 варианта:

  1. поместите эти два свойства в интерфейс, реализуйте этот интерфейс из типов t 2 и добавьте ограничение where T : ISomeInterface к Serialization<T>
  2. , используйте dynamic для переключения типа "утка" ксвойства
0 голосов
/ 28 июня 2011

Если у вас есть только два класса, я думаю, что следующий код сериализации может хорошо вас обслуживать

//The method is used to serialize classes above, classes are passed as generic types
                public void Serialization<T>(ref T engine)
                {
                    try
                    {
                        Type genericType = typeof(T);

                        if (typeof(MyClass1).Equals(genericType))
                        {
                            MyClass1 engineClass1 = engine as MyClass1;
                            //DO something for class 1
                        }
                        else if (typeof(MyClass2).Equals(genericType))
                        {
                            MyClass2 engineClass2 = engine as MyClass2;
                            //DO something for class 2
                        }

                    }
                    catch (Exception e)
                    {
                        //If Exception occurs I would like to write values to passed class properties, how to do that?
                        Result = false;
                        EngineErrorMessage = e.Message;
                    }
                }
...