I've defined the following generic class
public class ManagedClass<T> where T : ManagedClass<T>
{
static ManagedClass()
{
Manager = new ObjectManager<T>();
}
public static ObjectManager<T> Manager { get; protected set; }
public ManagedClass()
{
Manager.Add( (T)this );
}
}
The idea is that I can use it like so:
class Product : ManagedClass<Product> {}
Now I can do something to the 7th product created like so:
Product.Manager.GetById(7).DoSomething();
The problem comes in if i try to use a derived class:
class ExtendedProduct : Product {}
now ExtendedProduct.Manager has a list of 'Products', and if i want to use a new function that I have added to ExtendedProduct (DoSomethingElse), I have to cast the object I get back like so:
((ExtendedProduct)ExtendedProduct.Manager.GetById(7)).DoSomethingElse();
This is a bit ugly, and the whole point of using generics for this is to avoid casting. I suppose I could add a static constructor to the derived class to set Manager = new ObjectManager() and add a new Manager.addObject( this ) in the derived class constructor, but It seems like there should be some better way of doing this using generics. Any suggestions?
The problem is that ExtendedProduct.Manager is the same thing as Product.Manager; the manager object can't act differently depending on where it's accessed from.
A couple of possibilities I can think of:
Hide the typecast inside the GetById method by making it generic:
Product.Manager.GetById<ExtendedProduct>(7).DoSomethingElse();
Use one ObjectManager instance per subclass, connecting them privately if needed
Option 1 reminds me of NHibernate's ICriteria interface. It's effectively the same as a typecast, but a little harder to accidentally break.
Really what you're running into is a weakness with Generics. Once your class has resolved what type it's using for generics, you're somewhat restricted in what you can do.
Normally, I'd say Dependency Injection would be a savior here, but since the problematic method is static, that muddies up the waters.
I'd say the best thing is to have the ObjectManager class do the work for you:
static public class ObjectManager<T>
{
... the code that already exists in ObjectManager ...
static public U GetById<U>(long id)
{
object obj = GetById(id);
if (obj is U)
return (U)obj;
return default(U);
}
}
Then, in your code:
ExtendedProduct.Manager.GetById<ExtendedProduct>(7).DoSomethingElse();
It's not really tons more elegant than casting, but may be one of the only solutions using Generics.
Related
I have an abstract class called Flight and its implement a interface called IFlight and it has a virtual method, another three classes that inherit from it, the only diffrence between those three classes is the implemantation of this method. Another thing that I want to do is implement a method that accepts as an argument an object of type IFlight (could be one of those three classes) and from them i want to access the members of the abstract class (Flight). Which way there is to implement such thing ?
Flight:
class AbsFlight: IFlight
{
public int ID { get; set; }
public string Start_Point { get; set; }
public virtual float Calculate_Price(float Base_Price)
{
return Base_Price;
}
}
One of the classes (The other two looks similar except the method "Calculate_Price"):
class Charter: AbsFlight
{
public override float Calculate_Price(float Base_Price)
{
return base.Calculate_Price(Base_Price) * 3;
}
}
Main:
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2)); //OK
Console.WriteLine(flight.ID); //Error
}
static void Main(string[] args)
{
List<IFlight> flights = new List<IFlight>();
flights.Add(new Regular());
flights.Add(new Charter());
flights.Add(new LowCost());
Main_SomeMethod(flights[0]);
}
Your current solution, in combination with some of the suggestions, will be a case of a mounted riding rider. You don't need an interface and a base class and testing for type.
You can solve your problem the way you're trying, with a base class and an interface. But it's overkill, and you have to kind of duplicate some stuff in the interface and the base class.
You can solve your problem with a simple base class and three derived classes where only Calculate_Price gets overridden. Put the common items in the base class. This is a very simple solution, easy to figure out, especially if C# and OOP is new to you.
You can also solve your problem with an interface and three classes, not derived. This has the disadvantage that you have to implement the interface in three classes. As Peter Csala points out, C# 8 has some language features that can help minimize this work, possibly making this just as simple as using only a base class and no interface. I am not too familiar with those features, so I can't judge whether it makes sense.
Then there is another option entirely. This touches on what zaitsman hinted at - that this is possibly an XY problem. Why do you want to distinguish between Regular, Charter and LowCost using classes derived from Flight/AbsFlight? Is it possible to just have an attribute that tells what price profile is used? Are there other fields and properties of a Flight that has nothing to do with the price, and yet also distinguishes flights? Perhaps just use one class.
About testing for class type. This is what we call code smell. Generally, if you test for class types a lot, then you defy the purpose of using classes and/or interfaces in the first place.
Your method should accept the type that has the properties it needs, in this case the AbsFlight class.
private static void Some_Method(AbsFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
Console.WriteLine(flight.ID); //OK
}
But let's says the method must accept any IFlight. In this case, it can't be sure it received an AbsFlight; it has to check. After the check you can just cast.
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
if (flight is AbsFlight)
{
Console.WriteLine(((AbsFlight)flight).ID); //OK
}
}
With c#7 there is an additional construct you can use, if you think it is clearer:
private static void Some_Method(IFlight flight)
{
Console.WriteLine(flight.Calculate_Price(2));
switch (flight)
{
case AbsFlight absFlight:
Console.WriteLine(absFlight.ID); //OK
break;
}
}
It seems to be that you are doing something wrong that this is your requirement.
When you use an interface and pass it as an argument you want it to be common to all the objects that implement it.
Anyway, if you do want to do it. You might do something like:
if (flight is Flight)
{
Flight yourFlight = (Flight)flight;
// Here you can use anything you need from Flight, e.g: yourFlight.ID
}
My program have two classes; both derive from same base class.
class A : MyBase
{
internal A(InitVal initVal)
}
class B : MyBase
{
internal B(InitVal initVal)
}
InitVal is another class which is injected through constructor. This class is for internal usage. Due to internal constructor, user cannot create instance of class A and B directly. Instead, I created method which creates these objects.
class Initiator
{
InitVal initVal;
public T CreateObject<T>(ObjectInstance objectInstance) where T : MyBase
{
MyBase myBase = null;
switch(objectInstance)
{
case ObjectInstance.A:
myBase = new A(initVal);
break;
case ObjectInstance.B:
myBase = new B(initVal);
break;
}
return (T)myBase;
}
...
}
ObjectInstance is enum in above code.
This works without problem but I am sure you have never seen such ugly code earlier.
Please suggest creational pattern I should use. I want to remove ObjectInstance enum without changing functionality. It will cleanup much.
I tried Creational Patterns mentioned on dotfactory.
Factory Method and Abstract Factory does not look proper in this case.
My code even though look ugly, it is very simple to read and understand. I tried implementing patterns mentioned above which increases code complexity. So this is also my criteria while choosing answer.
I cannot change anything in code except Initiator class. All other classes are not accessible to me for edit.
Edit 1: Why above code is ugly in my view
1) While calling CreateObject method, user have to specify type of the object twice.
A a = initiator.CreateObject<A>(ObjectInstance.A);
First for T generic value and second to enum value.
I want to avoid this.
2) As user has to specify type of object twice, there are chances of mistake.
A a = initiator.CreateObject<A>(ObjectInstance.B);
In above code, enum value and generic value are different.
This is not allowed and will be a problem.
With my code, I cannot avoid this.
That is why; I am looking for pattern that suits my case without increasing complexity.
If I remove necessity of enum somehow, code will be lot better.
If I can change signature of CreateObject to following, it will be lot better.
public T CreateObject<T>() where T : MyBase
But, I am not sure how I will implement this method to create proper instances.
It doesn't look to me like you are getting any advantage from trying to make this generic. You needs to know the concrete type of the returned value at the call site.
Therefore why not keep things simple and just do this?
public class Initiator
{
InitVal initVal;
public A CreateA()
{
return new A(initVal);
}
public B CreateB()
{
return new B(initVal);
}
}
As you specified the method as generic one, I expect you might actually know the type you want to get already during the compilation time.. so I'd go for something like this:
class Initiator
{
public T CreateObject<T>(ObjectInstance objectInstance) where T : MyBase, new()
{
T newInstance = new T();
newInstance.Value = initVal;
return newInstance;
}
...
}
now you can call it as:
A myAInstance = initiator.CreateObject<A>();
MyBase myAInstance = initiator.CreateObject<A>(); //this also works
To make it work you need to specify an internal parameterless constructor in your classes and specify interface for the Value property or whatever you would set now in your current constructor.
class MyBase{
InitVal Value { get; set;} //this allows construction of the object with parameterless constructor
...
}
This is not only cleaner and shorter, but also less error prone, as you dont need to edit both enum and method body every time new type is added. It gives less flexibility for child-type specific logic, though.
NOTE: If you really want to have constructor with parameters as you have now you still can go for this approach but you'd need to use reflection (check Activator) or lambdas.
Of course this makes only sense if you can decide on the type during compilation time or you if you just want to delegate this decition to a 3rd party library, eg:
switch(chosenType){
case ObjectInstance.A:
instance = initiator.CreateObject<A>();
...
Otherwise, simply leave it as it is, its a FactoryMethod pattern more or less and it does the job. Just that the generic parameter in it... seems to be quite useless then. I would remove it and change return type to MyBase, as user won't be able to specify T anyway.
One last option is to simply create a separate method for each type, this is clean, flexible, gives a lot of options for customization, but sucks if you need to repeat a lot of shared logic and you need to add a new one for each next type. Simply:
A CreateObjectA(InitVal initValue){
return new A(initValue);
}
B CreateObjectB(InitVal initValue){ ...
One obvious problem with your code is the enum, which is unnecessary, because typeof(T) already gives you the appropriate type:
class Initiator
{
readonly Dictionary<Type, Func<MyBase>> _dict = new Dictionary<Type, Func<MyBase>>();
internal Initiator(InitVal initVal)
{
// initialize your "service locator".
// it's cool that different types can have different constructors,
// and people who call CreateObject don't need to know this.
_dict[typeof(A)] = (Func<MyBase>)(() => new A(initVal));
_dict[typeof(B)] = (Func<MyBase>)(() => new B(initVal, someOtherStuff));
}
public T CreateObject<T>() where T : MyBase
{
var ctor = _dict[typeof(T)];
return (T)ctor();
}
}
Alternatively, if you don't know the type, you can pass the enum, but then the return type should be an interface/base class (preferably interface):
// this is more likely, you probably don't need a generic method
public IMyBase CreateObject(ObjectInstance objectInstance)
{
// the dictionary would map enum value to Func<IMyBase>, of course
var ctor = _dict[objectInstance];
return ctor();
}
And now you have a simple "poor man's" DI class called Initiator, so I wonder if your DI framework (the one which injected InitVal) can also inject A and B instances. Which is probably true, since DI purists will tell you there is no place for factories and the new keyword in your code.
Btw, ObjectInstance is a really, really bad name for an enum.
I did it in following way:
class A : IMyType
{
internal A(InitVal initVal)
}
class B : IMyType
{
internal B(InitVal initVal)
}
class Initiator
{
InitVal initVal = .....;
public T CreateObject<T>() where T : IMyType
{
IMyType myType = null;
if(typeof(T) == typeof(A))
myType = new A(initVal);
else if(typeof(T) == typeof(B))
myType = new B(initVal);
else
throw new MyException("Type is not configured.");
return (T)myType;
}
...
}
This resolves the problems I mentioned in my question. But, it creates new problem. This violates open-close principle of SOLID. Last else block handles the manual mistake if any. Anyway, it just works for my specific case; not recommended generally.
I have the following architecture(the analogy sucks but W/E).
In program and other logic classes I have lots of methods that uses the specific type of the finger (MonkeyFinger). This mean that i have to explicitly cast in all those testMethods.
Is there any design pattern/solution to avoid explicit casts?
EDIT Code:
Monkey govi = new Monkey(...)
Program test = new Program()
test.testFinger1((MonkeyFinger) govi.GetHand.getFinger)
...
You can try something like this:
public class Animal<TFingerType> where TFingerType : IFinger
{
Hand<TFingerType> GetHand()
{
//... Do something
}
}
public class Monkey : Animal<MonkeyFinger> { }
public class Hand<TFingerType> where TFingerType : IFinger
{
}
public interface IFinger
{
}
public class MonkeyFinger : IFinger {
}
At least in your given example, it doesn't make sense for a Monkey to return a hand which contains HumanFingers. The hand itself is really defined by what type of fingers it has.
Then your code becomes:
Monkey govi = new Monkey(...)
Program test = new Program()
test.testFinger1(govi.GetHand.getFinger() /* getFinger here returns a MonkeyFinger */)
Note that the fingers are still IFingers, and can be used in that context, but this approach also provides concretely typed fingers.
I think it is best to create a method to do the checking for you. And yes, the casting is necessary if you want to test on some assumptions (like a monkey having only monkey fingers).
Something like:
public static T TestAndConvert<T>(object o)
{
Assert.IsInstanceOfType(o, typeof(T));
return (T)o;
}
Here you first check if the type is correct and then you return a typed instance. This way you are sure the type is correct and you have proper testing.
Use it in your test calls:
testFinger1(TestAndConvert<MonkeyFinger>(finger));
(From your diagram I am not sure if you use an automated test framework, like Unit Tests in Visual Studio, I recommend to do so)
Is there a real need to pass concrete finger to test method? When you are using interface you are define a contract which each implementation should follow. You can extend parent behavior in child class (or replace it but it's not correspondent with Liskov substitution principle) with method overriding but you test only contract then why do you need to pass MonkeyFinger insted of IFinger in test method?
N.B., this is all C# 4.0
This might seem like an odd question, let us say that all my business objects bind to a base class, let's call it BaseObject, so I'll have my classes inherit it like so:
public class CashRegister : BaseObject { }
Now most of the time I'm using, say, NHibernate on my projects. Some other projects come along and I'd like to use CouchDb. Rather than create a new BaseObject for each of these technologies, I'd like to somehow "bind" something like CouchDbObject to BaseObject ... is this possible? Even better would be if I had an attribute and it would bind based on the attribute:
[CouchDb]
public class CashRegister : BaseObject { }
This might be crazy, but is it possible? Given the above example, I'd liek to do this:
var cashRegister = new CashRegister();
cashRegister.SomeGenericBaseObjectMethod();
cashRegister.SomeCouchDbSpecificMethod();
It seems that Ninject "contextual binding" does what I need, does it? I'm brainstorming right now, but it would be great if somewhere in my code I could do something like this to do the actual binding:
Bind<ICouchDbObject>.To<BaseObject>();
I would even be up for making BaseObject dynamic, or any other bleeding edge features that might make this possible. If this is not possible or a "don't," let me know! Trying to think outside the box.
No, what you're asking isn't possible, for a couple of reasons.
.NET doesn't allow one class to directly inherit from multiple classes.
The project needs to refer to the parent class's library when it is compiled, so it can't be assigned a new parent class at runtime.
Usually when you run into a situation where you want to do what you're describing, it's because you're using an architecture that doesn't separate concerns well enough. I'm just guessing here, but you'll probably be more flexible if you use an approach like this:
public interface IBaseObject
{
int ObjectId {get;}
}
public class CashRegister : IBaseObject
{
int IBaseObject.ObjectId { get {return CashRegisterId;} }
public int CashRegisterId {get;set;}
}
public class BaseObjectUtil
{
public void SomeGenericBaseObjectMethod(IBaseObject baseObject)
{
var objectId = baseObject.ObjectId;
// Do something with the object ID.
}
}
public class SomeUtility
{
private BaseObjectUtil _baseObjectUtil;
public SomeUtility(BaseObjectUtil baseObjectUtil)
{
_baseObjectUtil = baseObjectUtil;
}
public void DoSomethingImportant(CashRegister register)
{
_baseObjectUtil.SomeGenericBaseObjectMethod(register);
}
}
You'll notice that so far we don't have any code that relies on CouchDb. Now, say there's another project that wants to be able to use the above project, but wants to be able to perform additional operations based on the CouchDb information. You might do something like this:
public interface ICouchDbObject
{
string TableName {get;}
}
public class CouchDbUtil
{
public void SomeCouchDbSpecificMethod(ICouchDbObject couchDbObject)
{
var tableName = couchDbObject.TableName;
// Do something with the table name.
}
}
public class CouchDbCashRegister : CashRegister, ICouchDbObject
{
string ICouchDbObject.TableName {get{return "CashRegisters";}}
}
In this project, when you need a cash register, you would use a CouchDbCashRegister, which would allow you to call the CouchDb-specific methods on your CouchDbUtil class, while still allowing you to call the baseline utility methods in your BaseObjectUtil class.
Furthermore, if you leverage a DI framework like Ninject to create your objects, you can actually make it so that all CashRegisters that get created in your second project are actually CouchDbCashRegisters.
Bind<CashRegister>.To<CouchDbCashRegister>();
Although your question discusses "binding" to another base class, you haven't shown any example usage that would leverage polymorphism. Rather, your example shows a hopeful ability to call an additional method:
var cashRegister = new CashRegister();
cashRegister.SomeGenericBaseObjectMethod();
cashRegister.SomeCouchDbSpecificMethod();
Are you mostly hoping for some syntactical sugar? If so, consider extension methods. Here is an example:
// Declaration
namespace ExtensionMethods {
public static class CashRegisterExtensions {
public static void SomeCouchDbSpecificMethod(this CashRegister cashRegister) {
// do stuff with CashRegister instance
}
}
}
Then you can do cashRegister.SomeCouchDbSpecificMethod();. Otherwise, if you're not just looking for syntactic sugar, you can consider using dynamic - but can you post some practical usage for what you're trying to accomplish that would take advantage of polymorphism?
In broad terms, for your classes to be reusable in different contexts, you need to decouple then from said contexts. Then, you'd have to create adapters, or proxies, for each context that you want to support.
In C#, you can create your objects as a kind of mixin object and then use them in your target classes:
public interface MBaseObject { }
public static class BaseObjectCode {
public static void SomeGenericBaseObjectMethod(this MBaseObject self) {
// ...
}
}
public interface MCouchDbObject { }
public static class CouchDbObjectCode {
public static void SomeCouchDbSpecificMethod(this MCouchDbObject self) {
// ...
}
}
public class CashRegister : MBaseObject, MCouchDbObject {
// ...
}
This uses a combination of interface inheritance and extension methods to create a kind of mixin. I've described it better here and here.
First thing to note - I KNOW DELEGATION AND DECORATOR PATTERNS!
Second - I am using C# .NET 4.0, so if you come up with a solution that is specific for it, that's fine. But if solution will work for any OOP language and platform, that would be great.
And here the question goes...
I have a partial class (lets name it Class1), which I cannot modify. Thus, I can just extend it or/and inherit from it. This class provides a perfect data model for me, the only thing I need is to add some attributes to its properties (for validation, defining label text value in MVC etc - for now, I do not need answers like 'you can do what you need without attributes', that's not the matter of my question).
It is not a problem to use another class as a data model, so I can, say, create Class2 : Class1 and use Class2 as a model. Properties that need attributes would be defined as public new <type> <propertyname>. This will limit me to rewriting only the properties that need attributes, leaving all other untouched.
The smaller problem is that I do not what to redefine getters and setters for the properties, as all they gonna contain is return base.<propertyname> and base.<propertyname> = value, and if there are lots of such properties, this means lots of "stupid" coding. Is there a way to avoid this?
The bigger problem is that I have to parametrize my Class2 with Class1 instance and make something like class2.<propertyname> = class1.<propertyname> for each single property I have - too much of "stupid" coding. I can avoid it using reflection - find all properties with public getters and setters in Class1 and call prop.SetValue(child, prop.GetValue(parent, null), null); in the loop. This provides a generic function for simple cases, which is quite fine, as I mostly have simple models - lots of properties with public getters and setters without body and another logic. But I want more generic solution, and I do not like reflection. Any ideas?
Here goes the full code of the extension method that creates Class2 basing on Class1
public static Child ToExtendedChild<Parent, Child>(this Parent parent)
where Child : Parent, new()
{
Child child = new Child();
var props = typeof(Parent).GetProperties().Where(p => p.GetAccessors().Count() >= 2);
foreach (var prop in props)
{
prop.SetValue(child, prop.GetValue(parent, null), null);
}
return child;
}
(by the way, this method may not ideally implement my solution, so any corrections would also be appreciated)
Thanks in advance!
The smaller problem doesn't seem to be much of a problem. Maybe I'm misunderstanding the question, but assuming you're simply deriving a subclass, there should be no reason to redefine either the properties or their associated getters/setters.
The bigger problem might be resolved using something a little simpler. Using reflection for a lot of your object initialization seems a little expensive. If you're dealing with a class that is primarily a big bag or properties, maybe you should as if you need access to all of those properties in any given situation. You mention MVC and validation, is the entire model being used in the controller method you're validation is taking place in? If not, why not look at using a viewmodel that only exposes those pieces you need in that method?
Your reflection initializer is interesting, but if you're going to be doing a lot of this then you might consider investing a little time with Automapper. Otherwise maybe consider moving away from a generic solution to something that just tackles the problem at hand, i.e. mapping properties from an instance of an object to another instance of a derived object. Maybe you can create a copy constructor in the parent class and use that in your derived class?
public class Foo {
public string PropOne { get; set; }
public string PropTwo { get; set; }
public Foo(string propOne, string propTwo) {
PropOne = propOne;
PropTwo = propTwo;
}
public Foo(Foo foo) {
PropOne = foo.PropOne;
PropTwo = foo.PropTwo;
}
}
public class Pho : Foo {
// if you have additional properties then handle them here
// and let the base class take care of the rest.
public string PropThree { get; set; }
public Pho(string propOne, string propTwo, string propThree)
: base(propOne, propTwo) {
PropThree = propThree;
}
public Pho(Pho pho) : base(pho) {
PropThree = pho.PropThree;
}
// otherwise you can just rely on a copy constructor
// to handle the initialization.
public Pho(Foo foo) : base(foo) {}
}
I assume the partial class is generated code, it makes the most sense given your scenario.
I know of one way to do this, but depending on how the attribute gets crawled, it may not work.
// Generated Code
public partial Class1
{
public string Foo { get { ... } }
}
// Your Code
public interface IClass1
{
[MyAttribute]
public string Foo { get; }
}
public partial Class1 : IClass1
{
}
If someone were to look at attributes by using GetCustomAttributes with inheritance, then I think they would get this attribute.
As an aside, whenever I see generated code that doesn't have virtual properties it makes me cry a little bit inside.
To address your bigger question, why don't you just make Class2 a wrapper for Class1. Instead of copying all of the properties you can just give Class2 an instance of Class1 in the constructor, store it locally and make all of your properties pass-throughs. It means some hand coding, but if you're building a Class2 by hand anyway and want to decorate it with a bunch of attributes, well, you're hand coding Class2 anyway.