Interface how do I get any Customer? - c#

we have an interface with a Generic Customer (gold/silver), now lets say i stored the last created cutomer somewhere (Cache/DB/etc).
how do i create a GetCustomer method that returns the type of customer.
Should i add GetCustomer to the base class or interface or elsewhere ? and how do we use GetCustomer ?
Hope that makes sense.
interface ICstomerInterface<T>
{
T MakeCustomer();
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public string Type { get; set; }
public string Name { get; set; }
// methods
public abstract T MakeCustomer();
}
public class Gold : BaseCustomer<Gold>
{
public override Gold MakeCustomer()
{
var customer = new Gold
{
Type= "Gold",
Name = "Jack"
};
return customer;
}
}
public class Silver : BaseCustomer<Silver>
{
public override Silver MakeCustomer()
{
var customer = new Silver();
customer.Name = "Jones";
customer.Type = "Silver";
return customer;
}
}

The problem with you design is that MakeCustomer is an instance method of the customers. This means, that you must create a customer to be able to call MakeCustomer. In other words, this design will not work!
You have two options: Either simply initialize the customers in their respective constructors, or create a customer factory. This must be a separate class (static or not).
The generic type parameter is superfluous.
public abstract class CustomerBase
{
public CustomerBase(string name)
{
Name = name;
}
public abstract string Type { get; }
public string Name { get; }
}
public class GoldCustomer : CustomerBase
{
public GoldCustomer(string name)
: base(name)
{
}
public override string Type => "Gold";
}
public class SilverCustomer : CustomerBase
{
public SilverCustomer(string name)
: base(name)
{
}
public override string Type => "Silver";
}
The Type property can be a getter only property. It can be abstract in the base class to force concrete customer classes to implement it.
The name must be passed to the constructor to be able to assign different names to different customers.
See also Abstract factory pattern on Wikipedia.
Example:
var customers = new List<CustomerBase> {
new GoldCustomer("Frank"),
new SilverCustomer("Jack")
};
foreach (CustomerBase c in customers) {
Console.WriteLine($"{c.Name} is {c.Type}");
}
Prints:
Frank is Gold
Jack is Silver
See working example: https://dotnetfiddle.net/BiAskT

You could have an extension method to get the customer type (on a static class):
public static Type GetCustomerType<T>(this ICstomerInterface<T> _customer)
{
return typeof(T);
}
All with the intention that you don't have to make redundant code each time you create a new Customer class that implements that interface.

Your sample code doesn't contain a base type that can contain all your customers, i.e. there is no strongly-typed variable that could hold either a BaseCustomer<Gold> or a BaseCustomer<Silver>. There is no type compatibility between those two at all, no more than a Dictionary<int> can be stored as a Dictionary<string> (in fact, even worse, because there isn't covariance in your object model). Given that fact, your question makes little sense, because you'll always have to declare the type parameter to store a customer somewhere, therefore there is no need to learn the type at run time.
But let's say you want a cache that works for both. You'd introduce a non-generic base interface:
public interface ICustomer
{
Guid CustomerGuid { get; }
}
public abstract class BaseCustomer<T>: ICstomerInterface<T>, ICustomer
{
///etc....
Now you can define a cache that could hold all customers:
var cache = new Dictionary<Guid,ICustomer>();
var gold = new Gold();
cache.Add( gold.CustomerGuid, gold );
var silver = new Silver();
cache.Add( silver.CustomerGuid, silver );
Now you can retrieve any customer by its Guid:
var customer = cache[guid];
And to determine its type, just use
bool isGold = customer is Gold;
bool isSilver = customer is Silver;
Or to get a string that tells you the type:
string type = customer.GetType().Name;

It appears that you are trying to use the classic Factory Method.
Personally for simple classes, like the one you are asking about, I would add a static method on the base class, like so:
public abstract class BaseCustomer<T>: ICstomerInterface<T>
{
public static BaseCustomer<T> GetLastCustomer()
{
// Get from storage, the last customer.
}
}
That way your Create customer method is separate from your get customer method but still accessible from anywhere.

Related

Generic Extension Method with Concrete Class Override

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 >();
}
}

Can I create an instance of a derived class based on a certain property defined in my abstract base class?

Basically I have an abstract class with we'll say two properties, one being abstract and some derived classes.
public abstract class BaseClass {
public string ID { get; set; }
public abstract string Name { get; };
}
public class Class1 : BaseClass { // id would be 1
public string Name { get { return "Class1 Name"; }
}
public class Class2 : BaseClass {
public string Name { get { return "Class2 Name"; }
}
public class Class3 : BaseClass {
public string Name { get { return "Class3 Name"; }
}
Then I have a method in my data layer that returns basically a list of ID's for the base class. What I'm asking is if I can create a new instance of the DerivedClass based on what these ID's are without if or switch statements? So...
List<BaseClass> list = new List<BaseClass>();
string id = dataReader["ID"].ToString(); // say this id = 1
list.Add(new BaseClass { ID = id }); // this would be "Class1 Name" and the Class would be Class1
I know I can't create a new instance of an abstract class so the 'new BaseClass()' doesn't work, but that's the only way I know how to explain it. I've looked into making a copy or clone with Reflection, but not sure if it's actually going to do what I want. This very well might not be possible, but figured I'd ask.
How about:
switch(id) {
case "1": list.Add(new Class1());
break;
...
}
You could also use:
list.Add((BaseClass)Activator.CreateInstance("AssemblyName", "Class"+id));
see also How do I instantiate a class given its string name?
Create a dictionary that contains the types associated with their ids (which its value will be in the string property you will depend on):
Dictionary<string, Type> dictOfTypes = new Dictionary<string, Type>();
dictOfTypes.Add("1", typeof(Class1));
Then depending on the id you have you can get the item from the Dictionary and then create the instance:
string id = "1";
Type classType = dictOfTypes[id];
var instance = Activator.CreateInstance(classType);

Access to different object properties through an interface? C#

I am programming a dll with a factory pattern on C#. The factory receive an enum and return an interface. Depending on the received enum it create different objects and return it encapsulated in the interface. Any class inside the factory implements the interface and its access modifier is internal, except the own interface which is public.
The problem is when i call the dll from the main project. Each object created inside the factory has different properties and do not why i can not access or modify those properties from the main. Some help?
this is the Factory call from the main.
IConfigurator config = ConfigFactory.Instance.CreateConfigurator(Model.First);
This is how the factory works (inside the dll):
public IConfigurator CreateConfigurator(Model model)
{
switch (model)
{
case Model.First:
return (First)new First(model);
case Model.Second:
return (Second)new Second(model);
case Model.Third:
return (Third)new Third(model);
}
}
First, Second and Third has different properties and i am not able to modify it from the interface object received
Thanks.
The short answer is that you're returning an interface, therefore only the properties that are part of the interface are available until you cast the object to its concrete type.
For example:
public class A : INameable
{
public string Name { get; set; }
public int Age { get; set; }
}
public class B : INameable
{
public string Name { get; set; }
public string Description { get; set; }
}
public Interface INameable
{
string Name { get; set; }
}
public Enum Selector
{
A,
B
}
So if I use a method as follows
public INameable GetINameable(Selector selector)
{
if (selector.Equals(Selctor.A))
return new A { Name = "Name A", Age = 10 };
if (selector.Equals(Selector.B))
return new B { Name = "Name B", Description = "New Instance of B"};
}
I will get an instance of INameable returned and will only be able to access the Name property as defined in the interface.
However if I need to access the other properties then I need to cast the returned object to its concrete type as follows:
// This will be an instance of INameable
var obj = GetINameable(Selector.A);
// Now cast as an instance of A
var castObj = obj as A;
// We can now access the Age property
var age = castObj.Age;
The method can have only one return type.
Instead of chossing result by enum, create different factory method / factory class for every item.
Sample:
// instead of this
public enum FactoryEnum {
VariantA,
VariantB,
VariantC
}
object Create(FactoryEnum item);
// do this
IMyInterfaceA CreateA();
IMyInterfaceB CreateB();
IMyInterfaceC CreateC();

Covariance with derived classes in C#

I have the following code (ready to paste into linqpad). Basically there is a base 'model' class with a 'treemembermodel' class deriving from it.
class MemberModel
{
public List<Member> Team = new List<Member>();
public void IncreaseAge()
{
// Would like this to modify the Treemember
Team[0].Age++;
}
}
class TreeMemberModel : MemberModel
{
public new List<TreeMember> Team = new List<TreeMember>();
public void UpdateName(string newName)
{
}
}
Same for a Member class with a 'TreeMember' deriving from it.
public class Member
{
public string Name;
public int Age;
}
public class TreeMember: Member
{
public string ParentName;
}
The idea is that the base member model stores a list of normal members, while the 'tree' model (and member) classes ensure a 'tree' structure by maintaining integrity between parent and subordinate fields.
This all seemed a good idea (the below example is stylised) - I figured any 'common' methods applying to both object types (eg 'increaseage' below) would modify the treeMember in the TreeModel when called from that model. However, calling 'increaseage' in my main method instead tries to access the 'Team' collection from the base 'MemberModel' instead, which of course doesn't exist.
void Main()
{
TreeMemberModel t = new TreeMemberModel();
t.Team.Add(new TreeMember() { Name = "original", Age = 10 });
// Call method within derived class
t.UpdateName("changed");
Console.WriteLine (t.Team[0].Name);
// Call method which drops down to base class method, and would like it to modify the TreeMemberModel's Team collection, not MemberModel's.
t.IncreaseAge();
Console.WriteLine (t.Team[0].Age);
}
I figure this is a covariance issue, and have tried a few things around making classes generic and so forth. Can I configure this so it drops back to the base class's methods while manipulating the elements of the TreeModel collection?
You should try following:
class MemberModel<TMember> where TMember : Member
{
public List<TMember> Team = new List<TMember>();
public void IncreaseAge()
{
// Would like this to modify the Treemember
Team[0].Age++;
}
}
class TreeMemberModel : MemberModel<TreeMember>
{
public void UpdateName(string newName)
{
}
}

how to specify optional anonymous ienumerable parameters in c# abstract method

I have the following base class
public abstract class BaseRepository<T>
{
public abstract IEnumerable<T> GetAll();
}
And a class the inherits it.
public class CustomerRepository: BaseRepository<Customer>
{
public override IEnumerable<Customer>GetAll()
{
return null;
}
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
what i want to do is using this class
public class Sales
{
public int Id { get; set; }
public int CustomerId {get;set;}
public decimal Total {get;set;}
}
this doesn't work
public class SalesRepository: BaseRepository<Sales>
{
public override IEnumerable<Sales>GetAll(IEnumerable<Customer> Customers)
{
return null;
}
}
My question is, how to I modify my BaseClass to have optional ienumerable parameters of that i can then use as needed.
The GetAll(IEnumerable<Customer> Customers) function amounts to a new method. It does not have the same signature of the base, and so cannot be overridden in this way. The SalesRepository class, if it is to be a BaseRepository<Sales>, must implement the GetAll() method as is.
You can do this change
public class SalesRepository : BaseRepository<Sales>
{
public override IEnumerable<Sales> GetAll()
{
return GetAll(null);
}
public IEnumerable<Sales> GetAll(IEnumerable<Customer> Customers)
{
return null;
}
}
BaseRepository<Sales> rep = new SalesRepository();
rep.GetAll();
this will call overridden version and makes a call to GetAll(null).
To pass value to GetAll() method you need to have do the following
SalesRepository srep = new SalesRepository();
srep.GetAll(new Customer[] { new Customer() });
You can either mark parameter as optional or you can make overloads to the method in your base class, both of which will result in the same thing. When you mark a parameter as optional the compiler simply makes the overloads for you.
Ultimately you probably need to make two methods in your base class and then either hide one (make private) in your implementation of each parent class or have it throw an error. If you can figure out a good way to have default values then that may work as well.

Categories

Resources