i have a class Product that contains a Dictionary with a price curve. The key is a string that can be parsed to a TimeStamp.
public class Product
{
public virtual int Id { get; set; }
public virtual IDictionary<string, decimal> PriceList { get; set; }
public Product()
{
this.PriceList = new Dictionary<string, decimal>();
}
}
Now i need a second class with more prices for each key
public class SpecialProduct : Product
{
public enum PriceType
{
BusineesDays,
Weekends,
Holidays
}
public virtual IDictionary<string, IDictionary<PriceType, decimal>> PriceList { get; set; }
public SpecialProduct()
{
this.PriceList = new Dictionary<string, IDictionary<PriceType, decimal>>();
}
}
I am not sure if this is a good approach for this case. I would also like to constrain the enum type to decimal. Any ideas?
UPDATE: I forgot to mention that i need to save all products i a generic List (List)
This is hiding a member.
Polymorphism means changing method, property implementation in some subclass, say it "derived" or "inherited" class. But, anyway, it's signature is immutable.
C# provides a good way of hiding members: the "new" keyword.
You just need to put "new" before access modifier in the derived class and you got it. If you don't do that, C# compiler will suggest you to do that.
By the way, if your goal is using polymorphism, you should take generics in account.
Your base class should have a "TPriceValue" generic parameter and it'll look like this:
public class Product<TPriceValue>
{
public virtual int Id { get; set; }
public virtual TPriceValue PriceList { get; set; }
public Product()
{
// NOTE/EDIT: You wouldn't initialize "PriceList" here...
}
}
So, if you want your price value to be a decimal, you should instantiate your class this way:
new Product<decimal>();
Or, if you want that your value as another dictionary:
new Product<IDictionary<PriceType, decimal>>();
If I'm not wrong, this is the way to go in your case ;)
EDIT: Sorry I forgot to change something in your base class, check again this answer :)
I would go for simplification, since this code has a certain bad smell to it.
Why don't you use the PriceList in SpecialProduct inside Product as well, and make the sub-dictionary have just one value always of PriceType.Default or something like that? You would then be able to use all Products without requiring any casts or checks.
What about this approach?
public abstract class AProductBase<T>
{
public IDictionary<string, T> PriceList { get; set; }
...
}
public class Product : AProductBase<decimal>
{
...
}
public enum PriceTypeEnum { ... }
public class SpecialProduct : AProductBase<IDictionary<PriceTypeEnum, decimal>>
{
...
}
Perhaps this fits better your requirements.
Regards
Related
I have a third party DLL that returns objects like Customers, Orders, etc. I'll call them Your Entities. They do have a common IYourEntity interface so I can use that as a source constraint.
I want to create a generic conversion extension method to convert all these different third party entities to My Entities with some streamlined and more maintainable code.
....but I can't figure out how to make a generic extension method that will call the concrete extension method for the specific conversion of each class.
Putting some of the main aspects of my code below, but you can get a full fiddle to play with here.
Yes, I'm probably showing I'm a bit clueless on how to do this and maybe trying to combine different concepts. Any pointers much appreciated as I've been beating my head for a couple of days now and need a life line :)
public interface IYourEntity
{
int Id
{
get;
set;
}
}
public interface IConvertToMyEntity<TYourEntity, TMyEntity>
where TYourEntity : class, IYourEntity, new()
where TMyEntity : class, IMyEntity, new()
{
TMyEntity ToMyEntity(TYourEntity yourEntity);
}
public static class ExtensionMethods
{
private static IMyEntity ToMyEntity(this IYourEntity yourEntity)
{
return new MyEntity1();
}
public static List<IMyEntity> ToMyEntityList(this List<IYourEntity> lstYourEntities)
{
return lstYourEntities.ConvertAll(q => q.ToMyEntity());
}
}
public class YourEntity1 : IYourEntity, IConvertToMyEntity<YourEntity1, MyEntity1>
{
public int Id
{
get;
set;
}
public string YourEntityName
{
get;
set;
}
public MyEntity1 ToMyEntity(YourEntity1 yourEntity)
{
return new MyEntity1()
{Id = yourEntity.Id, MyEntityName = yourEntity.YourEntityName, CreatedOn = DateTime.UtcNow};
}
public List<MyEntity1> ToMyEntityList(List<YourEntity1> lstYourEntities)
{
return lstYourEntities.ConvertAll(q => ToMyEntity(q));
}
}
Since the classes implementing IYourEntity are from a third party and not under your control, you can't implement an own IConvertToMyEntity<T1, T2> interface upon these.
One way you can handle it is by overloads of such conversion (extension) methods.
There's no need for any generic T type arguments; the common IYourEntity interface suffices.
Suppose you have 3 classes implementing the IYourEntity interface;
e.g. YourCustomer, YourOrder and YourProduct.
These need to be converted to IMyEntity instances, of which you might have different concrete implementations;
e.g. a general MyEntity and a specific MyProduct.
For the conversion you set up an extension method targeting IYourEntity.
This extension method will be called to convert an IYourEntity to an IMyEntity in case a more specific overload of this extension method does not exist.
public static IMyEntity ToMyEntity(this IYourEntity target)
{
return new MyEntity { Id = target.Id, EntityName = "Fallback name" };
}
For the entities that require a custom conversion, you set up overloads of this extension method targeting those specific source class types.
Below are such ones for YourOrder and YourProduct (but not for YourCustomer).
public static IMyEntity ToMyEntity(this YourOrder target)
{
return new MyEntity { Id = target.Id, EntityName = target.OrderName.ToUpper() };
}
public static IMyEntity ToMyEntity(this YourProduct target)
{
return new MyProduct { Id = target.Id * 100, EntityName = target.ProductName };
}
Next, define the extension method to convert the list of IYourEntity instances to a list of IMyEntity instances. In the code below, the inbetween cast to dynamic enables that the appropriate ToMyEntity overload will be called.
Note that the ToMyEntity methods don't have to be extension methods, but it might be convenient to have these in place in case you need to convert a single instance instead of a list.
public static List<IMyEntity> ToMyEntities(this List<IYourEntity> target)
{
var myEntities = new List<IMyEntity>();
foreach (var yourEntity in target)
{
var myEntity = Extensions.ToMyEntity((dynamic)yourEntity);
myEntities.Add(myEntity);
}
return myEntities;
}
An example - .net fiddle
var yourEntities = new List<IYourEntity>()
{
new YourCustomer() { Id = 1 },
new YourOrder() { Id = 2, OrderName = "Order-2"},
new YourProduct() { Id = 3, ProductName = "Product-3"}
};
var myEnties = yourEntities.ToMyEntities();
myEnties.ForEach(o => Console.WriteLine("{0} - {1} ({2})",
o.Id, o.EntityName, o.GetType().Name
));
The output of the example above looks like below.
Notice how the YourCustomer instance was handled by the general IYourEntity conversion, whereas the YourOrder and YourProduct instances got a specific treatment.
1 - Fallback name (MyEntity)
2 - ORDER-2 (MyEntity)
300 - Product-3 (MyProduct)
You can change your extension method to this:
private static IMyEntity ToMyEntity(this IYourEntity yourEntity)
{
if (yourEntity is IConvertToMyEntity<IYourEntity, IMyEntity> convertible)
return convertible.ToMyEntity;
return new MyEntity1();
}
This will not work in most cases unless you also make your interface co- and contra-variant:
public interface IConvertToMyEntity<in TYourEntity, out TMyEntity>
where TYourEntity : class, IYourEntity, new()
where TMyEntity : class, IMyEntity, new()
{
TMyEntity ToMyEntity(TYourEntity yourEntity);
}
It is still not completely clear to me how you can make a third party class implements IConvertToMyEntity that easily. Assuming you did this only to show us your actual goal, you should be very careful with what you are trying to accomplish in the Main.
If you use a List<IYourEntity>, you can only use methods and properties defined in the interface, unless you know what you are doing with specific cast. The need for List<IYourEntity> or List<IMyEntity> limits a lot the implementation of a custom mapper between My classes and Your classes. Here a possible solution:
As I said, I did not change Your classes:
public interface IYourEntity
{
int Id
{
get;
set;
}
}
public class YourEntity1 : IYourEntity
{
public int Id
{
get;
set;
}
public string YourEntityName
{
get;
set;
}
}
Also My classes are very simple and do not contain any logic for the mapping. This is a debatable choice, but I generally prefer to keep conversion logic separated from the classes involved. This helps to maintain clean your code in case you have several conversion functions for the same pair of classes. By the way, here they are:
public interface IMyEntity
{
int Id
{
get;
set;
}
DateTime CreatedOn
{
get;
set;
}
}
public class MyEntity1 : IMyEntity
{
public int Id
{
get;
set;
}
public string MyEntityName
{
get;
set;
}
public DateTime CreatedOn
{
get;
set;
}
}
And this is how I designed the custom converter
public interface IMyEntityConverter
{
IMyEntity Convert(IYourEntity yourEntity);
}
public class MyEntity1Converter : IMyEntityConverter
{
public IMyEntity Convert(IYourEntity yourEntity)
{
var castedYourEntity = yourEntity as YourEntity1;
return new MyEntity1()
{
Id = castedYourEntity.Id,
MyEntityName = castedYourEntity.YourEntityName,
CreatedOn = DateTime.UtcNow
};
}
}
It is clear the lack of genericity, but you cannot do otherwise if you need an extension method on a List of generic My and Your classes. Also tried with covariant and contravariant interfaces but C# does not let you use them with this implementation.
Now the core of the solution: you need something that binds Your class to the My class with a custom converter, and all of this should be as more transparent as possible.
public class EntityAdapter<YourType, MyType>
where YourType : IYourEntity
where MyType : IMyEntity
{
protected YourType wrappedEntity;
protected IMyEntityConverter converter;
public EntityAdapter(YourType wrappedEntity, IMyEntityConverter converter)
{
this.wrappedEntity = wrappedEntity;
this.converter = converter;
}
public static implicit operator YourType(EntityAdapter<YourType, MyType> entityAdapter) => entityAdapter.wrappedEntity;
public static explicit operator MyType(EntityAdapter<YourType, MyType> entityAdapter) =>
(MyType) entityAdapter.converter.Convert(entityAdapter.wrappedEntity);
public MyType CastToMyEntityType()
{
return (MyType) this;
}
}
The pseudo-transparency here is given by the implicit cast to Your class. The advantage is that you can cast this EntityAdapter to an instance of a My class by calling CastToMyEntityType or the explicit operator overload.
The painful part is with the extension methods:
public static class EntityAdapterExtensions
{
public static List<IMyEntity> ToIMyEntityList(this List<EntityAdapter<IYourEntity, IMyEntity>> lstEntityAdapters)
{
return lstEntityAdapters.ConvertAll(e => e.CastToMyEntityType());
}
public static List<EntityAdapter<IYourEntity, IMyEntity>> ToEntityAdapterList(this List<IYourEntity> lstYourEntities)
{
return lstYourEntities.Select(e =>
{
switch (e)
{
case YourEntity1 yourEntity1:
return new EntityAdapter<IYourEntity, IMyEntity>(yourEntity1, new MyEntity1Converter());
default:
throw new NotSupportedException("You forgot to map " + e.GetType());
}
}).ToList();
}
}
The first one is pretty straightforward to understand, but the second one is definitely something that require maintenance. I gave up on generics for the reasons already explained, so the only thing left to do is to create the EntityAdapters starting from the actual entity types.
Here is the fiddle
This may be a little controversial but maybe a different way is better?
Firstly, and this is more for my sake, I would suggest more easily understandable terminology so instead of 'your' and 'my' I would use 'source' and 'dest'.
Secondly I wonder if the generics route is necessary? I'm assuming (and I may be wrong) that for each of the classes you have coming from your third-party assembly, you have a specific class for it to be converted to. So maybe this could be achieved much more easily with a constructor override in your destination class.
// third party class example
public class SourceClass
{
public int Id { get; set; }
public string Name { get; set; }
}
// the destination class in your project
public class DestClass
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
// default constructor
public DestClass()
{
}
// conversion constructor
public DestClass(SourceClass source)
{
Id = source.Id;
Name = source.Name;
CreatedOn = DateTime.UtcNow;
}
}
This way you convert a single instance using:
// source being an instance of the third-party class
DestClass myInstance = new DestClass(source);
And you can convert a list with LINQ:
// source list is IList<SourceClass>
IList<DestClass> myList = sourceList.Select(s => new DestClass(s)).ToList();
If you wanted to you could implement extensions for your conversions. This again would not be generic as you'll need one for each class pairing but as it's an alternative to writing a converter class for each, it will be overall less code.
public static class SourceClassExtensions
{
public static DestClass ToDest(this SourceClass source)
=> new DestClass(source);
public static IList<DestClass> ToDest(this IList<SourceClass> source)
=> source.Select(s => new DestClass(s)).ToList();
}
If you still want something generic then you'll want a converter for each class pair, implementing a suitable interface. Then I'd recommend a converter factory class where you'll need to register the specific converters either into a dictionary in the class or via dependency injection. I can go into this further if you'd prefer but I think it would be more complicated.
sorry for writing here its not an actual answer,
there is no option for generically to do this
you have to write for every entity
public interface IConvertToMyEntity<TYourEntity, TMyEntity>
where TYourEntity : class, IYourEntity, new()
where TMyEntity : class, IMyEntity, new()
{
TMyEntity ToMyEntity(TYourEntity yourEntity);
}
I saw this code from your question.
It depends on what you want to do after transformation
you should use data mapper
public class MapProfile : Profile
{
public MapProfile()
{
CreateMap<TYourEntity , TMyEntity >();
CreateMap<TMyEntity , TYourEntity >();
}
}
I have multiple classes that have a fled called "rows" however the rows field is of a different class type for each table.
So in the below example I have a fish table and a bird table. The table class is essentially the same but the rows field is of a specific class type making it easy for someone to reference properties on that object.
XXX.rows[0].canfly would be easy to reference if it's a bird.
So now I'm trying to write a generic method that can fetch multiple instances of FishTable or BirdTable .. do some magic, merge them into one table of that type and return the result. All the method needs to know is what type of table we're talking about and a few other basic parameters.
I know I'm approaching this incorrectly but I can quite tell where I'm falling down.
9 out of 10 times I run into something like this:
Severity Code Description Project File Line Suppression State
Error CS0311 The type 'GenericTest.FishTable<GenericTest.fish>' cannot be
used as type parameter 'T' in the generic type or method 'Tester.test<T>()'.
There is no implicit reference conversion from
'GenericTest.FishTable<GenericTest.fish>' to
'GenericTest.ITable<GenericTest.FishTable<GenericTest.fish>>'. GenericTest
C:\Users\WarrickF\source\repos\EOSTools\GenericTest\Program.cs 14 Active
I know I need to go an really understand Generics as I really no have business writing Generics like this without a descent understanding but .. well this is a real example I'm working through.
interface ITable<T>
{
List<T> rows { get; set; }
}
public class BirdTable<T> : ITable<T>
{
public List<T> rows { get; set; }
}
public class FishTable<T> : ITable<T>
{
public List<T> rows { get; set; }
}
public abstract class animal {
public int eyeCount;
}
public class bird : animal
{
public int featherCount;
public bool canFly;
}
public class fish : animal
{
public int numberOfFins;
public bool depth;
}
Chetan Ranpariya's comment is right on. I can try to help a bit anyway, but it's partly guesswork. You want to merge multiple tables, with rows of type T, but the error message seems to indicate that your code somewhere expects individual Ts instead.
There is no implicit reference conversion from
'GenericTest.FishTable<GenericTest.fish>' to
'GenericTest.ITable<GenericTest.FishTable<GenericTest.fish>>'.
There are rather more problems here, though. Your interface is working against you, and your class hierarchy is going to waste. So I'd suggest you simplify. First, I don't think you need a BirdTable<T> or FishTable<T>, because the T itself parameterizes the table type. You just need a TestTable<T> where T : animal.
Then in a method that merges them, you provide T and also where T : animal before the body's opening brace. Since they're parameterized by T, it's not possible to mix different table types.
I've taken the liberty of copying and then reworking what you did, below. I hope you find this helpful for getting insights into using generics. They do take some time to get used to. P.S., I've standardized your code to the usual naming conventions and encapsulation approaches in C#.
class Program
{
static string _animal;
static void Main(string[] args) {
TestTable<Bird> birds1 = new TestTable<Bird>();
birds1.Rows.Add(new Bird());
birds1.Rows.Add(new Bird());
TestTable<Bird> birds2 = new TestTable<Bird>();
birds2.Rows.Add(new Bird());
birds2.Rows.Add(new Bird());
TestTable<Bird> allBirds = MergeTestTables<Bird>(birds1, birds2);
int howManyBirds = allBirds.Rows.Count;
Console.WriteLine($"There are { howManyBirds } { _animal }s.");
Console.ReadKey(true);
}
public static TestTable<T> MergeTestTables<T>(params TestTable<T>[] tables) where T : Animal {
TestTable<T> merged = new TestTable<T>();
_animal = typeof(T).Name;
_animal = _animal.ToLower();
foreach (TestTable<T> table in tables) {
foreach (T row in table.Rows) {
merged.Rows.Add(row);
}
}
return merged;
}
public class TestTable<T> where T : Animal
{
public List<T> Rows { get; set; } = new List<T>();
}
public abstract class Animal
{
public int EyeCount { get; set; }
}
public class Bird : Animal
{
public int FeatherCount { get; set; }
public bool CanFly { get; set; }
}
public class Fish : Animal
{
public int NumberOfFins { get; set; }
public bool Depth { get; set; }
}
}
I am experiencing some issues in creating a nested object structure in C# using Dictionaries & Generics (I am using Visual Studio, .NET Framework 4.6+)
The main problem is the absence of covariance in C# Dictionaries.
I have to create this simple (JSON serializable/deserializable) object structure in C#. I try to explain using the animals...
public class AnimalCatalog
{
public Dictionary<string, Animal> AnimalsDict { get; set; } // key is the species name
}
public class Animal // base class
{
public string Species { get; set; } // univocal
public bool CanFly { get; set; }
public Dictionary<string, GenericPaw> PawsDict { get; set; } // each animal has a different type and a different number of paws
}
public class GenericPaw // base class
{
public int FingerNumber { get; set; } // number of finger in each paw
}
public class Cat : Animal // derived class
{
public void meow() // only cats says 'meow'
{...}
}
public class CatPaw : GenericPaw // derived class
{
public void scratch() // cats paws could scratch something :) but not all the animals paws could
{...}
}
I implemented this structure using C# generics, because a Cat has a dictionary of CatPaws, not generic Paws :P. this is my proposal.
public class AnimalCatalog<T,V> where T : Animal<V> where V : GenericPaw
{
public Dictionary<string, T> AnimalsDict { get; set; } = new Dictionary<string, T>(); // key is the species name
}
public class Animal<T> where T : GenericPaw // base class
{
public string Species { get; set; } // univocal
public bool CanFly { get; set; }
public Dictionary<string, T> PawsDict { get; set; } // each animal has a different type and a different number of paws
}
public class GenericPaw // base class
{
public string PawName { get; set; } // univocal
public int FingerNumber { get; set; } // number of finger in each paw
}
public class Cat<T> : Animal<T> where T : CatPaw // derived class
{
public void meow() // only cats says 'meow'
{...}
}
public class CatPaw : GenericPaw // derived class
{
public void scratch() // cats paws could scratch something :) but not all the animals paws could
{...}
}
let's use the created class
Cat<CatPaw> Kitty = new Cat<CatPaw>(); // create a cat
CatPaw KittyFirstPaw = new CatPaw(); // create the 1st cat's paw
Kitty.PawsDict.Add(KittyFirstPaw.PawName, KittyFirstPaw); // add the paw to the dict
AnimalCatalog<Animal<GenericPaw>,GenericPaw> ZooCatalog = new AnimalCatalog<Animal<GenericPaw>,GenericPaw>(); // create a catalog of animals
Animal<GenericPaw> GenericAnimal = Kitty; <-- doens't compile (can't convert derived to base class)
AnimalCatalog.AnimalsDict.Add(GenericAnimal.Species, GenericAnimal);
I also tried using an interface instead of a base class, using the out keyword to specify T as a covariant type, but it doesn't work because I can't use a covariant type in a dict...
Any help is very appreciated :)
Stefano
You can't convert Cat<CatPaw> to Animal<GenericPow>, because then you could add a different kind of GenericPaw into its dictionary (for example a DogPaw) and the cat wouldn't appreciate that.
This is only a problem because you can insert new values in the dictionary, so it seems like it could be solved by using an IReadOnlyDictionary, but unfortunately that one isn't covariant either because of technical issues as described in this question.
On a side note, is there a reason why Cat is also generic?
public class Cat<T> : Animal<T> where T : CatPaw
That would be useful if you want to create a cat that can only have certain specific paws derived from CatPaw. If not, this could become:
public class Cat : Animal<CatPaw>
The AnimalCatalog also seems like it's unnecessarily complex. If you only ever need an animal catalog of Animal, it could be simplified to just one generic parameter:
public class AnimalCatalog<TPaw> where TPaw : GenericPaw
{
public Dictionary<string, Animal<TPaw>> AnimalsDict { get; set; }
}
and if you only ever need an AnimalCatalog<GenericPaw>, you could get rid of the one parameter too. But it's still the case that this catalog would not be very useful since you can't convert an Animal<CatPaw> to Animal<GenericPaw>.
To solve this, you could create a convariant interface of IAnimal<out TPaw> that has all the properties of an Animal but instead of the dictionary, you could either expose paws as an IEnumerable<TPaw> Paws and if you need the dictionary lookup, a method: TPaw GetPaw(string pawName). These would be implemented using the dictionary. Then it's possible to convert a Cat ( which is an Animal<CatPaw> and therefore also IAnimal<CatPaw>) to IAnimal<GenericPaw>. Your animal catalog will then contain IAnimal<GenericPaw>.
Only Interfaces and Delegates allow Covariance. See Microsoft Docs.
I have some classes with common properties, however, I cannot make them derive from a base type (LINQ-to-SQL limitations).
I would like to treat them as if they had a base type, but not by using Reflection (performance is critical).
For example:
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
}
public class Vehicle
{
public int Id { get; set; }
public string Label { get; set; }
}
In this case I would be happy if I had the Id property available, regardless of the type I'm holding.
Is there any way in C# to to something similar to this:
public static int GetId<T>(T entity) where T // has an int property 'Id'
{
return entity.Id;
}
I guess I could have used dynamic, however, I'm looking for a way to restrict the code in compile time from using this method for an object that has no Id property.
You can use interfaces:
public interface IHasId
{
int Id { get; }
}
public class User : IHasId { ... }
public class Vehicle : IHasId { ... }
public static int GetId<T>(T entity) where T : IHasId
{
return entity.Id;
}
However, if you are not able to modify the classes to add the interface, you won't be able to do this. No compile-time checks will verify that a property exists on T. You'd have to use reflection - which is slow and obviously not ideal.
There is no way to guarantee a type has a given member without constraining to a common base type or interface. One way to work around this limitation is to use a lambda to access the value
public static int Use<T>(T value, Func<T, int> getIdFunc) {
int id = getIdFunc(value);
...
}
Use(new User(), u => u.Id);
Use(new Vehicle(), v => v.Id);
You can create an interface with the common properties and make your classes implement it:
public interface IEntity
{
int Id { get; set; }
}
public class User : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
}
public class Vehicle : IEntity
{
public int Id { get; set; }
public string Label { get; set; }
}
public static int GetId<T>(T entity) where T : IEntity
{
return entity.Id;
}
You could simplify GetId like this:
public static int GetId(IEntity entity)
{
return entity.Id;
}
The other answers mentioning the interface approach are certainly good, but I want to tailor the response to your situation involving Linq-to-SQL.
But first, to address the question title as asked
Can C# constraints be used without a base type?
Generally, the answer is no. Specifically, you can use struct, class, or new() as constraints, and those are not technically base types, and they do give some guidance on how the type can be used. That doesn't quite rise to the level of what you wish to do, which is to limit a method to types that have a certain property. For that, you will need to constrain to a specific interface or base class.
For your specific use case, you mention Linq-to-SQL. If you are working from models that are generated for you, then you should have options to modify those classes without modifying the generated model class files directly.
You probably have something like
// code generated by tool
// Customer.cs
public partial class Customer // : EntityBaseClasses, interfaces, etc
{
public int ID
{
get { /* implementation */ }
set { /* implementation */ }
}
}
And other similar files for things such as Accounts or Orders or things of that nature. If you are writing code that wishes to take advantage of the commonly available ID property, you can take utilize the partial in the partial class to define a second class file to introduce a common interface type to these models.
public interface IIdentifiableEntity
{
int ID { get; }
}
And the beauty here is that using it is easy, because the implementation already exists in your generated models. You just have to declare it, and you can declare it in another file.
public partial class Customer : IIdentifiableEntity { }
public partial class Account : IIdentifiableEntity { }
// etc.
This approach has proven valuable for me when using a repository pattern, and wishing to define a general GetById method without having to repeat the same boilerplate in repository after repository. I can constrain the method/class to the interface, and get GetById for "free."
Either you need to make both classes implement an interface with the properties you need, and use that in the generic constraint, or you write separate methods for each type. That's the only way you'll get compile-time safety.
This might be a simple one, but my head is refusing to wrap around that, so an outside view is always useful in that case!
I need to design an object hierarchy to implement a Parameter Registration for a patient. This will take place on a certain date and collect a number of different parameters about a patient (bloodpressure, heartrate etc). The values of those Parameter Registrations can be of different types, such as strings, integers, floats or even guids (for lookup lists).
So we have:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public class ParameterRegistrationValue
{
public Parameter Parameter { get; set; }
public RegistrationValue RegistrationValue { get; set; } // this needs to accomodate the different possible types of registrations!
}
public class Parameter
{
// some general information about Parameters
}
public class RegistrationValue<T>
{
public RegistrationValue(T value)
{
Value = value;
}
public T Value { get; private set; }
}
UPDATE: Thanks to the suggestions, the model has now morphed to the following:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; }
}
public abstract class ParameterRegistrationValue()
{
public static ParameterRegistrationValue CreateParameterRegistrationValue(ParameterType type)
{
switch(type)
{
case ParameterType.Integer:
return new ParameterRegistrationValue<Int32>();
case ParameterType.String:
return new ParameterRegistrationValue<String>();
case ParameterType.Guid:
return new ParameterRegistrationValue<Guid>();
default: throw new ArgumentOutOfRangeException("Invalid ParameterType: " + type);
}
}
public Parameter Parameter { get; set; }
}
public class ParameterRegistrationValue<T> : ParameterRegistrationValue
{
public T RegistrationValue {get; set; }
}
public enum ParameterType
{
Integer,
Guid,
String
}
public class Parameter
{
public string ParameterName { get; set; }
public ParameterType ParameterType { get; set;}
}
which is indeed a bit simpler, but now I'm wondering, since the IList in ParameterRegistration points to the abstract ParameterRegistrationValue object, how will I be able to get the actual value out (since its stored on the sub-objects)?
Maybe the whole generic thing is indeed not quite the way to go after all :s
If you don't know the final set of parameter and the corresponding type of each parameter then the generics probably won't help - use object as a parameter value type.
Furthermore iterating through the list of parameters will be a pain since you'll have to examine the type of each item in order to determine how to treat the value.
What are you trying to achieve with generics ? Yes, they are cool (and going for boxing/unboxing is probably not a best idea), but in some cases you might want to use object instead (for both simplicity and flexibility).
-- Pavel
What you might want to introduce is an abstract base class for RegistrationValue<T> that is not generic, so that your ParameterRegistrationValue class can hold a non-generic reference, without needing knowledge of the type involved. Alternatively, it may be appropriate to make ParameterRegistrationValue generic also, and then add a non-generic base class for it instead (so that the list of values in ParameterRegistration can be of different types.
1st way:
public abstract class RegistrationValue
{
}
public class RegistrationValue<T> : RegistrationValue
{
public RegistrationValue(T value)
{
Value = value;
}
public T Value { get; private set; }
}
And now your code should compile.
Once you have a non-generic base class, I'd also move any members of the generic class that don't depend on the generic type parameters up into this base class. There aren't any in this example, but if we were instead modifying ParameterRegistrationValue to be generic, I'd move Parameter up into the non-generic base class (because it doesn't depend on the type parameter for RegistrationValue)
May be, you should use public RegistrationValue RegistrationValue, where T - is type, using in generic. For example, T - is String or other class or struct.
Or you should make class ParameterRegistrationValue as generic, to use generic argument in the field RegistrationValue.
I believe you want to have a collection of instances of different RegistrationValues-derived classes and be able to iterate it and for to have different type for each element. That's rather impossible.
You'll still need to cast each element to the type you know it is, because iterating the collection will return references to your base type (ParameterRegistrationValue - this one specified by IList type parameter). So it won't make any real difference from iterating over non-generic object list.
And if you can safely do that casting for each parameter (you know all the types), you probably don't need collection like this at all - it'll be better to have a class that encapsulates all the parameters in one type, so that you can call it with strong types, with IntelliSense etc. like this:
public class ParameterRegistration
{
public DateTime RegistrationDate { get; set; }
public PatientData PatientData { get; set; }
public Guid Identifier { get; set; }
// ...
}