I have this class Project which I want to extract an interface out of, since we're going to work with different types of projects. One of the properties of Project however is called Data:
class Project {
public Data D {get;}
public void SomeSpecificMethodReferencingData()
{
D.SomeSpecificMethod();
}
}
class Data {
public void SomeGenericMethod() { }
public void SomeSpecificMethod() { }
}
Now, Data needs to be extracted as an interface as well (but only defining the SomeGenericMethod(). I am currently using this:
interface IProject {
IData D {get;}
}
interface IData {
void SomeGenericMethod();
}
class Data : IData {
public void SomeGenericMethod() { }
public void SomeSpecificMethod() { }
}
class OtherData : IData {
public void SomeGenericMethod() { }
public int SomeOtherSpecificMethod(float someArgument) { }
}
class Project : IProject {
public IData D { get; }
public void SomeSpecificMethodReferencingData()
{
D.SomeSpecificMethod(); // this does not work!
(D as Data).SomeSpecificMethod(); // this looks stupid!
}
}
class OtherProject : IProject {
public IData D { get; }
public void SomeOSpecificMethodReferencingOtherData()
{
var i = D.SomeOtherSpecificMethod(14.0f); // this does not work!
var i = (D as OtherData).SomeOtherSpecificMethod(14.0f); // this looks stupid!
}
}
The problem I run into is that within the Project class, I reference the SomeSpecificMethod. When I extract an interface for Data however, I first have to cast it from IData to be able to reference the specific method. This is not preferrable as the IData ALWAYS is an instance of Data for this Project. When I build my OtherProject I will create an OtherData for it, so to get pairs of xxxProject and xxxData implementations.
Is there a design pattern of some sort to help me building pairs of related and referenced classes? Like the Abstract Factory, but better?
You may use generics for that:
interface IProject<T> where T: IData {
T D {get;}
}
Now your different projects are this:
class Project : IProject<Data>
{
public Data D { get; }
public void SomeSpecificMethodReferencingData()
{
D.SomeSpecificMethod(); // D is of type Data
}
}
class OtherProject : IProject<OtherData> {
public OtherData D { get; }
public void SomeOSpecificMethodReferencingOtherData()
{
D.SomeOtherSpecificMethod(14.0f); // D is of type OtherData
}
}
you can have 3 separate interfaces:
interface IData:ISpecificData, IGenericData
{
}
interface ISpecificData
{
void SomeSpecificMethod();
}
interface IGenericData
{
void SomeGenericMethod();
}
you can use only one of the interfaces when you need only one of the methods, and use IData when you need both
In class Project you are referencing SomeSpecificMethod of Data class.
You are NOT using anything from IData interface - so using IData in Project class has no sense.
It is possible to do it as in your examples, and it will work - but it is "wrong way".
(D as Data).SomeSpecificMethod(); // this looks stupid!
It looks stupid - but from other reasons. What if D is not Data, but OtherData ? It will be perfectly correct at compile time, but it will blow up during runtime!
Related
I have a method as below
List<Customer> GetCusts = dataContext.Customers;
The customers table has a field called IsValued so i can do something like this
foreach (var c in GetCusts)
{
if(c.IsValued)
{
// do something
}
}
I have a products table doing the exact same thing also with the same column name
List<Product> GetProds = dataContext.Products;
foreach (var p in GetProds)
{
if(p.IsValued)
{
// do something
}
}
I thought to turn this into a Generic method (or better a class), so i can pass in a generic list a bit like
foreach (var p in GetData) // GetData could be a List<t> but of course i cant cast it.
{
if (p.IsValued)
{}
}
but of course IsValued does not exist. I know the reason why (due to it being a generic type) but after researching around to see if its possible i couldnt get a decent example and test it out or maybe i just didnt understand. Can anyone advise how this could be possible or lead me to an article to achieve this?
Edit 1
My attempt so far in a class, it could be wrong but to give an idea in case im on the wrong path. I assume i need a property of IsValued (which doesnt have to be of a bool value) in the GenericValue class?
public interface ICustomGenerics<T>
{
IEnumerable<T> GetData();
}
public class GenericValue<T> : ICustomGenerics<T> where T : class
{
public IEnumerable<T> GetAll()
{
_entities.
}
}
Here is how you can use an interface:
public interface IValued {
bool IsValued { get; set; }
}
public class Customer : IValued {
public bool IsValued { get; set; }
}
public class Product : IValued {
public bool IsValued { get; set; }
}
public void filterData<T>(List<T> data) where T: IValued {
foreach (var d in data) {
if (d.IsValued) {
}
}
}
As others pointed out you can either pick a base class and derive from that, or you can use an interface. I'd rather go with the interface in this case.
Assuming you are using Entity Framework, you can use a partial classes to apply your interface:
public interface IValuable
{
bool IsValued { get; set; }
}
and you'd have partial classes like:
public partial class Customer : IValuable
{
// IValuable implementation
public bool IsValued { get; set; }
}
public partial class Product : IValuable
{
// IValuable implementation
public bool IsValued { get; set; }
}
Now you can have a processor / service class that accepts these as generics with a condition that they should all implement this interface:
public class Processor<T> where T : IValuable
{
public Something Process(T parameter)
{
foreach (var p in GetData)
{
if (p.IsValued)
{
// Do stuff
}
}
}
}
Since you declared your generic to have IValuable implementation, the code below will know IsValuable is a member.
I suggest this approach over base classes because interfaces are best used this way to define common behaviour. You can even see the same pattern in the framework, IDisposable (which implements Dispose()) and IEnumerable / IEnumerator (which implements things like GetEnumerator(), MoveNext() etc) are two most common examples.
Background info
I have a set of interfaces/classes as follows. For the sake of simplicity imagine more properties, collections etc.
interface IMaster
{
//Some properties
}
interface IB : IMaster
{
string PropOnA { get; set }
}
interface IC : IMaster
{
string PropOnB { get; set }
}
class B : IB
class C : IC
...
These contracts were designed to store data(which is held in a slightly different format in each case). There is a lot of code that uses these contracts to get the data, format it, process it, write etc.
We have developed an entire library that does not see the concrete implementations(B,C) of any of these contracts by inverting control and allow the user to use our 'default implementations' for each contract or just loading in their own. We have registry where the user can register a different implementation.
To this end I have implemented a kind of strategy pattern where there exists a strategy for each contract type based on the task at hand. For the sake of simplicity lets say the task is writing, in reality it is much more complicated.
interface IWriteStrategy
{
public Write(IMaster thing);
}
class WriterA : IWriteStrategy
class WriterB : IWriteStrategy
etc
The above concrete strategies are also never 'seen' in our library, the client must register their own implementation or our default version.
Design flaw??
I am not liking the cast in every strategy that is now necessary.
public classWriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IA thingA)
//do some work
}
}
public classWriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
if(thing is IB thingB)
//do some work
}
}
What we want to do is be able to loop through a list of IMaster objects and run some operations.
foreach(var thing in Things)
{
var strategy = GetStrategy(thing.GetType()); //this gets the strategy object from our `registry` if one exists
strategy.Execute(thing);
}
The above design allows this but there seems to be a flaw which I cant for the life of me spot a solution to. We have to cast to the specific interface within each strategy implementation.
I have tried with generics, but just cant seem to nail it.
Question
What would be a better way of designing this to avoid the cast but still be able to loop through a list of IMaster things and treat them the same? Or is the cast absolutely necessary here?
I am trying to follow a SOLID design but feel the cast is messing with this as the client implementing the strategies will have to do the cast in order to get anything to work within the Write method.
[Edit]
I have updated the classes implementing the IWriteStrategy.
If you rarely add new IMaster specializations, but often add new operations OR need to make sure operation providers (e.g writer) needs to support ALL specializations then the Visitor Pattern is a perfect fit.
Otherwise you basically need some kind of service locator & registration protocol to map operation providers/strategies to IMaster specializations.
One way you could do it is define generic interfaces such as IMasterWriter<T> where T:IMaster which can then be implemented like IBWriter : IMasterWriter<IB> which defines the mapping.
From that point you only need a mechanism that uses reflection to find a specific IMasterWriter implementor for a given type of IMaster and decide what to do if it's missing. You could scan assemblies early to detect missing implementations at boot rather than failing later too.
Maybe it is appropriate to use Strategy pattern and just give an implementation and execute it. Let me show an example.
interface IMaster
{
void ExecuteMaster();
}
class MasterOne : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master One");
}
}
class MasterTwo : IMaster
{
public void ExecuteMaster()
{
Console.WriteLine("Master Two");
}
}
and
interface IWriteStrategy
{
void Write(IMaster thing);
}
class WriterA : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer A");
thing.ExecuteMaster();
}
}
class WriterB : IWriteStrategy
{
public void Write(IMaster thing)
{
Console.WriteLine("Writer B");
thing.ExecuteMaster();
}
}
and code to execute:
static void Main(string[] args)
{
List<IWriteStrategy> writeStrategies = new List<IWriteStrategy>()
{
new WriterA(),
new WriterB()
};
List<IMaster> executes = new List<IMaster>()
{
new MasterOne(),
new MasterTwo()
};
for (int i = 0; i < writeStrategies.Count(); i++)
{
writeStrategies[i].Write(executes[i]);
}
}
what about this, you will have all your casts in one strategy factory method:
public interface IWriterStrategy
{
void Execute();
}
public class WriterA : IWriterStrategy
{
private readonly IA _thing;
public WriterA(IA thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnA);
}
}
public class WriterB : IWriterStrategy
{
private readonly IB _thing;
public WriterB(IB thing)
{
_thing = thing;
}
public void Execute()
{
Console.WriteLine(_thing.PropOnB);
}
}
public static class WriterFactory
{
public static List<(Type Master, Type Writer)> RegisteredWriters = new List<(Type Master, Type Writer)>
{
(typeof(IA), typeof(WriterA)),
(typeof(IB), typeof(WriterB))
};
public static IWriterStrategy GetStrategy(IMaster thing)
{
(Type Master, Type Writer) writerTypeItem = RegisteredWriters.Find(x => x.Master.IsAssignableFrom(thing.GetType()));
if (writerTypeItem.Master != null)
{
return (IWriterStrategy)Activator.CreateInstance(writerTypeItem.Writer, thing);
}
throw new Exception("Strategy not found!");
}
}
public interface IMaster
{
//Some properties
}
public interface IA : IMaster
{
string PropOnA { get; set; }
}
public interface IB : IMaster
{
string PropOnB { get; set; }
}
public interface IC : IMaster
{
string PropOnC { get; set; }
}
public class ThingB : IB
{
public string PropOnB { get => "IB"; set => throw new NotImplementedException(); }
}
public class ThingA : IA
{
public string PropOnA { get => "IA"; set => throw new NotImplementedException(); }
}
public class ThingC : IC
{
public string PropOnC { get => "IC"; set => throw new NotImplementedException(); }
}
internal static class Program
{
private static void Main(string[] args)
{
var things = new List<IMaster> {
new ThingA(),
new ThingB()//,
//new ThingC()
};
foreach (var thing in things)
{
var strategy = WriterFactory.GetStrategy(thing); //this gets the strategy object from our `registry` if one exists
strategy.Execute();
}
}
}
i'm trying to build a sort of framework for some base process in an app. There is some common behavior where i have to execute some operations but these operations are different depending on some scenarios. I have done something i'm not sure if it's considered a bad practice to make something like this:
public interface IMyDto
{
string makerIdentifier { get; set; }
}
public class DtoOne:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteOne
}
public class DtoTwo:IMyDto
{
public string makerIdentifier { get; set; }
//Custom properties for ConcreteTwo
}
public abstract class AbstractMaker
{
public abstract void DoSomething(IMyDto myInterface);
}
public class ConcreteMakerOne:AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoOne;
// If concrete is not null..do stuff with DtoOne properties
}
}
public class ConcreteMakerTwo : AbstractMaker
{
public override void DoSomething(IMyDto myInterface)
{
var concrete = myInterface as DtoTwo;
// If concrete is not null..do stuff with DtoTwo properties
}
}
public class Customer
{
public void MakeSomething(IMyDto myDto)
{
var maker = GetMaker();
maker.DoSomething(myDto);
}
private AbstractMaker GetMaker()
{
//Stuff to determine if return ConcreteOne or ConcreteTwo
}
}
The code im not happy with is the:
var concrete = myInterface as DtoOne;
I would appreciate a lot if someone could give me some advide or tips about a pattern or good oop practice for this scenario.
It's not clear what all of your use cases are, but one option might be generics:
public abstract class AbstractMaker<T> where T:IMyDto
{
public abstract void DoSomething(T myInterface);
}
public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
public override void DoSomething(DtoTwo myInterface)
{
// now you are certain that myInterface is a DtoTwo
}
}
I am not sure if I understand correctly what are you asking about, but why not just put method DoSomething in IMyDto and implement it differently in DtoOne, DtoTwo, etc.? There would be only one Maker and would always call the same method.
lately I started to learn generics. I run into trouble with storing references to generic classes instances. As you can see, my class ListHandler can store references to specific type of BaseClass. I would love to register BaseClass instances by themselves, which is why I wanted to guarantee that they will use BaseParamClass by adding 'where'. Anyway - it does not compile.'This', does not know that T is actually BaseClassParam even with 'where' keyword in class. I don't know what is wrong here and I couldn't find answer anywhere. I would be grateful for tips/guides/solutions.
public class ListHandler
{
private List<BaseClass<BaseParamClass>> list;
public ListHandler()
{
list = new List<BaseClass<BaseParamClass>>();
}
public void Register(BaseClass<BaseParamClass> param)
{
list.Add(param);
}
}
public class BaseClass<T> where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this); //throws error
}
}
Why don't you make ListHandler generic as well?
public class ListHandler<T>
{
private List<BaseClass<T>> list;
public ListHandler()
{
list = new List<BaseClass<T>>();
}
public void Register(BaseClass<T> param)
{
list.Add(param);
}
}
public class BaseClass<T>
{
private ListHandler<T> listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler<T> listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Also, it seems strange to me to have BaseClass<T> contain a reference to a class that has a reference to BaseClass<T> itself.
I have another option for you.
Let's split the BaseClass<T> class into two with a non-generic base, like so:
public class BaseClass
{
protected ListHandler listHandler;
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
}
}
public class BaseClass<T> : BaseClass where T : BaseParamClass
{
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
: base(listHandler)
{
listHandler.Register(this); // Compiles nicely! Yay!
}
}
Now, the list inside ListHandler can be defined as private List<BaseClass> list;. That means there is no problem adding any BaseClass item to the list. We also can then define two methods for registering and fetching generic versions of the BaseClass<T> from the ListHandler. It would look like this:
public class ListHandler
{
private List<BaseClass> list;
public ListHandler()
{
list = new List<BaseClass>();
}
public void Register<T>(BaseClass<T> param) where T : BaseParamClass
{
list.Add(param);
}
public BaseClass<T> Fetch<T>() where T : BaseParamClass
{
return list.Select(x => x as BaseClass<T>).Where(x => x != null).FirstOrDefault();
}
}
So, given a class public class FooParam : BaseParamClass { } I can write this code:
ListHandler listHandler = new ListHandler();
BaseClass<FooParam> baseClass = new BaseClass<FooParam>(listHandler);
BaseClass<FooParam> baseClass2 = listHandler.Fetch<FooParam>();
Console.WriteLine(object.ReferenceEquals(baseClass, baseClass2));
The result from this code is True is written to the console - which means I can successfully fetch the instance of BaseClass<FooParam> from the ListHandler.
Why your code doesn't compile
In order to fully understand why your code doesn't compile, you'll have to dive into covariance and contravariance, which is a big topic and hard to explain in an SO answer. It can be especially confusing if you've gotten to a point where inheritance polymorphism is second nature to you; the rules are just different enough to be make your head hurt.
Here is what is confusing--
You're used to doing this:
object a = new String(...);
But generics don't let you do this!
List<object> c = new List<string>(); //Compiler error
That's because those two Lists are not related the same way that object and string are related. One does not inherit from the other. Rather, they are different variants of a generic type definition. In the generic world, you can't assign one to the other. The same is true of this:
void Foo<T>() where T: BaseParamClass
{
BaseClass<BaseParamClass> a = new BaseClass<T>(); //Compiler error
}
In this example, T could be BaseParamClass or one of its derived types. They are not the same type. So to remain type-safe, the compiler has to disallow this assignment, and your Register call, which has the same type mismatch.
Standard ways around this
You need a covariant interface. These allow assignment from derived to base. So for example, while this is still illegal:
List<object> a = new List<string>(); //Compiler error
This is totally fine:
IEnumerable<object> e = new List<string>(); //Is OK
Because IEnumerable was declared to be covariant, like this:
interface IEnumerable<out T>
Which means it is can be assigned in this way. It works because using out also adds a compiler constraint to the interface: it can be used to retrieve stuff...
interface IEnumerable<out T>
{
T Item[int index];
}
...but it cannot accept anything:
interface IEnumerable<out T>
{
Add(T item); //Compiler error
}
These constraints are what allow generics to provide early-bound type safety while still allowing certain forms of (non-inheritance) polymorphism.
What I'd suggest
Based on your comment, it sounds like you just need a container (a stack, apparently) that can hold references to these BaseClass<T> instances. If you are following separation of concerns, the stack doesn't need to actually do anything with the T, other than store it and retrieve it, and to allow it to register itself.
Since that is a separate concern, make a separate interface.
And in the interest of keeping things simple, maybe avoid using generics completely for this bit.
One way to do it--
Create an interface that allows access to everything the stack needs to know about an item it is containing. For example, if the stack contains popups of various kinds, you may want to expose the popup's title.
interface IStackable
{
string Title { get; set; }
}
Now use it like this:
public class ListHandler
{
private readonly Dictionary<string, IStackable> list;
public ListHandler()
{
list = new Dictionary<string, IStackable>();
}
public void Register(IStackable item)
{
list.Add(item.Title, item);
}
}
public class BaseClass<T> : IStackable where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
public string Title { get; set; }
}
Unless there is some other requirement, you shouldn't need to make it any more complicated than that.
All you really need to do is add an interface. This works:
public class BaseParamClass
{
}
public class ListHandler
{
private List<IBase<BaseParamClass>> list;
public ListHandler()
{
list = new List<IBase<BaseParamClass>>();
}
public void Register(IBase<BaseParamClass> param)
{
list.Add(param);
}
}
public interface IBase<T> where T : BaseParamClass
{
T Param {get; }
}
public class BaseClass : IBase<BaseParamClass>
{
private ListHandler listHandler;
public BaseParamClass Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Working code on DotNetFiddle
I'm trying to create two interface hierarchies, one for the business model objects and one for the ui. I know it's important to have loose coupling between the layers but part of the application will require drawing diagrams so I need the model objects to be readily available to their corresponding graphical representations and I have a common layer holding interfaces for the model objects..
Common class library code:
public interface IBase {}
public interface IBookObject : IBase {}
public interface ITapeObject : IBase {}
public class Book : IBookObject {}
Graphics layer code:
public interface IModelObject<T>
{
T ModelObject { get; set; } // might be a book or tape , etc
}
public class GraphicObject<T> : IModelObject<T>
{
public T ModelObject { get; set; }
}
Code use:
IBookObject bk = new Book();
var go = new GraphicObject<IBookObject>(); // will fail later
//var go = new GraphicObject<IBase>(); // will succeed later
go.ModelObject = bk;
if (go is IModelObject<IBase>) // can't use is IModelObject<IBookObject>
// as go might be GraphicObject<ITapeObject>
{
Debug.WriteLine("Success");
}
So if I want to test for IBase (and then access ModelObject), I have to make sure that the original object was created with IBase and not a derived interface, and this seems like a cause of bugs later. my questions are:
1) Am I doing something horrible?! :) I might be overlooking a better approach..
2) failing that, is there some way of using the new contravariance c# 4 techniques to make the is line test for any interface deriving from IBase? Alternatively I think it would work if IBook didn't inherit from IBase, but Book (and Tape) implemented both IBook and IBase separately.
3) failing that, is there any way to prevent construction of GraphicObject<IBookObject>() and GraphicObject<ITapeObject>()?
Thank you!
Would this work?
public interface IBase { }
public interface IBookObject : IBase { }
public interface ITapeObject : IBase { }
public class Book : IBookObject { }
public interface IModelObject
{
IBase ModelObject { get; set; } // might be a book or tape , etc
}
public class GraphicObject<T> : IModelObject
where T: class, IBase
{
public T ModelObject { get; set; }
#region IModelObject Members
IBase IModelObject.ModelObject
{
get
{
return ModelObject;
}
set
{
ModelObject=value as T;
}
}
#endregion
}
class Program
{
static void Main(string[] args)
{
IBookObject bk=new Book();
var go=new GraphicObject<IBookObject>(); // will fail later
//var go = new GraphicObject<IBase>(); // will succeed later
go.ModelObject=bk;
if(go is IModelObject) // can't use is IModelObject<IBookObject> as go might be GraphicObject<ITapeObject>
{
Debug.WriteLine("Success");
}
}
}