问题
I have two classes, which are passed to Serialization method and I would like to access two properties of these classes in Serialization method. The problem is that Serialization method parameter are passed as generic type and I do not know how to access properties of passed class in this case. The example below.
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;
}
}
Full method code
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;*/
}
}
回答1:
Declare an interface containing the properties Result
and EngineErrorMessage
. Now you have two options:
- Add a constraint to your serialization type parameter so that only types that derive from the interface mentioned above can be serialized, or
- In your catch block try to cast
engine
to the interface mentioned above. If the cast succeeds, write the propertie values, otherwise do nothing.
Sample:
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:
You will have to use reflection at some point, via typeof(T)
(or maybe engine.GetType()
). If this is a frequent code-path you may want to cache some kind of strategy per-type to avoid overhead. Or perhaps better: use a pre-built serialization API that optimises for this type of scenario (i.e. most of them).
If you mean the Result
and EngineErrorMessage
, then 2 options:
- put those two properties on an interface, implement that interface from the t 2 types, and add the
where T : ISomeInterface
constraint toSerialization<T>
- use
dynamic
to duck-type to the properties
回答3:
If you have only two classes to deal with I think following serialization code can server you well
//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;
}
}
来源:https://stackoverflow.com/questions/6502666/access-class-property-passed-as-generic-type