I have a data开发者_如何学JAVA access class that loads reference data. Each type of entity will execute it's own stored procedure and return a result set specific for that entity type. Then I have a method that maps the returned values from the datatable to the entity. All Entity Types have the same public properties of Code and Name how can I make this method generic to handle a type of entity? Something like this is what would presume but the properties are causing an error.
private static T MapDataReaderToEntity<T>(IDataReader reader)
{
var entity = typeof (T);
entity.Code = SqlPersistence.GetString(reader, "Code");
entity.Name = SqlPersistence.GetString(reader, "Name");
return entity;
}
and I would call it with something like this.
_sourceSystem = MapDataReaderToEntity<SourceSystem>(_reader);
You could have an interface that defines those properties, and then have your entity classes implement that interface:
public interface IEntity
{
string Code { get; set; }
string Name { get; set; }
}
Now, you can add a generic constraint to your method:
public static T MapDataReaderToEntity<T>(IDataReader reader) where T : IEntity, new()
{
T entity = new T();
// More code here...
}
Note that you also need the new()
constraint to actually construct the new entity; it indicates the any generic type argument will have a parameterless constructor.
If your entities implement an interface with the Code and Name properties defined, you could potentially use something like:
private static T MapDataReaderToEntity<T>(IDataReader reader)
where T : IEntity, new()
{
T entity = new T(); // typeof(T) would return the System.Type, not an instance!
entity.Code = SqlPersistence.GetString(reader, "Code");
entity.Name = SqlPersistence.GetString(reader, "Name");
return entity;
}
Without the interface, there is no way for the compiler to know about the Code
or Name
properties. You would need to revert to using Reflection or dynamic code, or some other less-than-ideal mechanism for determining these properties at runtime instead of at compile time.
You need to add a type constraint to MapDataReaderToEntity<T>
which ensures that any T implements Code and Name property setters, as well as a parameter-less constructor.
If all of your entities have properties Code
and Name
, I'd suggest having them implement an interface ICodedEntity
with properties Code
and Name
, then define your method
private static T MapDataReaderToEntity<T>(IDataReader reader) where T : ICodedEntity, new()
{
var entity = new T();
...
}
then the code you have will compile.
精彩评论