I am trying to achieve something like this:
interface IAbstract
{
string A { get; }
object B { get; }
}
interface IAbstract<T> : IAbstract
{
T B { get; }
}
class RealThing<T> : IAbstract<T>
{
public string A { get; private set; }
public T B { get; private set; }
}
So I can do something like this:
RealThing<string> rt = new RealThing<string>();
IAbstract ia = rt;
IAbstract<string> ias = rt;
object o = ia.B;
string s = ias.B;
Is this possible?
Very nearly. Three things:
You should use new in IAbstract<T> to indicate that you know you're hiding an existing member:
new T B { get; }
But even without that, you'll still only get a warning.
You need to implement the IAbstract.B within RealThing, which you should almost certainly do using explicit interface implementation, delegating to the strongly-typed member:
object IAbstract.B { get { return B; } }
Within your test code, you need to specify a type argument for RealThing:
RealThing<string> rt = new RealThing<string>();
This is fine, and even a reasonably common pattern for times where you want to be able to get a non-generic form of an interface.
Yes, with little changes
interface IAbstract
{
string A { get; }
object B { get; }
}
interface IAbstract<T> : IAbstract
{
new T B { get; }
}
sealed class RealThing<T> : IAbstract<T>
{
public string A { get; private set; }
public T B { get; private set; }
object IAbstract.B
{
get { return B; }
}
}
so you can write
var rt = new RealThing<string>();
IAbstract ia = rt;
IAbstract<string> ias = rt;
object o = ia.B;
string s = ias.B;
Actually the System.Collections.IEnumerator and System.Collections.IEnumerator<T> interfaces do that. When you implement IEnumerable<T>, you will have to implement one of the Current properties explicitly, usually you will pick the non-generic one for that:
object IEnumerable.Current
{
// this calls the implicitly implemented generic property
get { return this.Current; }
}
public T Current
{
get { return this.current; } // or however you want to do it
}
In this case you don't even need two interfaces. Just mark the interface as covariant (supported since C# 4):
interface IAbstract<out T>
{
string A { get; }
T B { get; }
}
and use IAbstract<object> wherever you used the non generic interface before.
Related
I have a class like this
public class OwnerWithholding
{
private decimal ManagementFeePct;
private decimal TotalManagementFee;
private decimal OperationalFeesPct;
private decimal TotalOperationalFees;
}
And I have calculation method that create object of this class, fill it with some arithmetic operations, and return this object.
public OwnerWithholding CalculationMethod1(Reservation r, SqlConnection conn)
{
OwnerWithholding result = new OwnerWithholding();
// result.ManagementFeePct = some data from Fees table in DB + value
//from another db - constant value..
// Also with other properties - with some operations on data
//result.TotalManagementFee = ..
// result.OperationalFeesPct = ..
// result. TotalOperationalFees = ..
return result;
}
And now it works fine.
But this calculation method is just one option for populating data.
There is another calculation method, implemented in a completely different way, but filling exactly the same properties of the object. And I may have more of them.
I need a pattern that would allow me to create objects of the same class, just indicating the calculation method that is needed.
I like the strategy pattern , where the algorithms will be the methods that fill the objects that called them.
But it doesn’t look very good.
Maybe a factory method would be more appropriate here, but I don’t know how to implement it.
Edit: Going by the OPs comments now, it looks like just ONE method in the class needs to be set in multiple ways.
The Template pattern (or the Builder) are better fits in this case, not the Factory.
Template Pattern.
a. Abstract Base class that set default properties, but leaves out one property (Get Ingredients) to be populated by the concrete classes.
public abstract class PizzaCreator
{
public abstract string GetIngredients { get; }
public string Bake { get; set; } = "Bake at 400F for 30 minutes";
public string Deliver { get; set; } = "Deliver in custom box";
}
b. Two Pizza classes, for now just overriding the abstract property
public class CheesePizza : PizzaCreator
{
public override string GetIngredients
{
get { return GetMyIngredients(); }
}
string GetMyIngredients()
{
return "Lots of Cheese!";
}
}
public class PepperoniPizza : PizzaCreator
{
public override string GetIngredients
{
get { return GetMyIngredients(); }
}
string GetMyIngredients()
{
return "Lots of Meats!";
}
}
Here I'm creating instances of the Pizza
var pepPizza = new PepperoniPizza();
var chessePizza = new CheesePizza();
You could even have these creations routed through a Factory class/method.
Original answer:
Here is the Abstract Factory Pattern.
This code goes into the Factory class library.
a.ICar interface
public interface ICar
{
string Name { get; set; }
int Doors { get; set; }
string EngineCapacity { get; set; }
}
b.Abstract Car Factory
public abstract class AbstractCarFactory
{
public abstract ICar CreateCar(CarType type);
}
c.Two Concrete Cars -
internal class NissanPickUpTruck : ICar
{
public string Name { get; set; }
public int Doors { get; set ; }
public string EngineCapacity { get ; set ; }
}
internal class NissanSportsCar: ICar
{
public string Name { get; set; }
public int Doors { get; set; }
public string EngineCapacity { get; set; }
}
d.Concrete Factory
public class NissanFactory : AbstractCarFactory
{
public override ICar CreateCar(CarType type)
{
switch (type)
{
case CarType.PickupTruck:
return new NissanPickUpTruck{Name = "Titan", Doors = 6, EngineCapacity = "V12"};
case CarType.SportsCar:
return new NissanSportsCar{Name = "350Z", Doors = 2, EngineCapacity = "V6"};
default:
throw new Exception();
}
}
}
Finally the calls from an external project
var nissanFactory = new NissanFactory();
var sportsCar = nissanFactory.CreateCar(CarType.SportsCar);
var pickUpTruck = nissanFactory.CreateCar(CarType.PickupTruck);
But like the other comment, the Builder is something worth checking out as well.
Well from the beginning, I've got a simple generic interface:
public interface IItemContainer<T> where T : Item
{
T ChosenItem { get; set; }
}
And an class that implements it multiple times:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
public FabulousItem ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
}
I can't make the ChosenItems of types NiceItem and GreedyItem public, and also I can't access it like this:
ChosenItem<GreedyItem> = new GreedyItem();
cuz' I've got an error:
'GreedyItem' is a type, which is not valid in the current context
Is there anyway to use those props in this manner or I've got it all wrong and should do It with Dictionary or other way?
When you like to keep your generic IItemContainer you can implement a GetChosenItem and SetChosenItem method like this.
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
FabulousItem IItemContainer<FabulousItem>.ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
public T GetChosenItem<T>()
where T : Item
{
return ((IItemContainer<T>)this).ChosenItem;
}
public void SetChosenItem<T>(T value)
where T : Item
{
((IItemContainer<T>)this).ChosenItem = value;
}
}
Which comes very close to what you were trying to do.
container.SetChosenItem<NiceItem>(new NiceItem());
Yours is a case explicit interface implementations were made for. You give your conflicting items a unique name and forward the items to the interface. That also avoids any naming confusions:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem> {
public FabulousItem ChosenFabulousItem { get; set; }
public NiceItem ChosenNiceItem { get; set; }
public GreedyItem ChosenGreedyItem { get; set; }
FabulousItem IItemContainer<FabulousItem>.ChosenItem {
get {
return ChosenFabulousItem;
}
set {
ChosenFabulousItem = value;
}
}
NiceItem IItemContainer<NiceItem>.ChosenItem {
get {
return ChosenNiceItem;
}
set {
ChosenNiceItem = value;
}
}
GreedyItem IItemContainer<GreedyItem>.ChosenItem {
get {
return ChosenGreedyItem;
}
set {
ChosenGreedyItem = value;
}
}
}
Assignment is simple:
container.ChosenFabulousItem = new FabulousItem();
container.ChosenNiceItem = new NiceItem();
container.ChosenGreedyItem = new GreedyItem();
If you have more complex conversion logic in the background (e.g. you assign a FaboulousItem and need to convert it into a NiceItem), you can do so by providing getters and/or setters for your public properties.
It's completely wrong. As you should know you cannot make same names for member items (properties, fields etc. ). It will confuse compiler.
I would suggest to modify your interface a bit like :
public interface IItemContainer
{
List<Item> ChosenItems { get; set; }
T ChosenItem<T>() where T : Item;
}
Now in your implementation :
public class ItemContainer : IItemContainer
{
IItemContainer.ChosenItems
{
get { // your implementation
}
set { // your implementation
}
}
T IItemContainer.ChosenItem<T>()
{
return ((IItemContainer)this).ChosenItems.OfType<T>().FirstOrDefault();
}
}
This method will let you store different objects that derive from Item and return desired one using ChosenItem<T>() method.
EDIT:
I've got another interface which operates on List of Items, cuz' some submodules works only on one Item, and some only on set. I need also to store an instance of each implemented type independently.
You can always use something like a factory collection ( dont know if the name is correct ).
public class ChosenItemCollection
{
Dictionary<Type, Item> _fac = new Dictionary<Type, Item>();
public T Add<T>(T item) where T : Item
{
if(!_fac.ContainsKey(typeof(T))
{
_fac.Add(typeof(T), item);
}
else
{
_fac[typeof(T)] = item;
}
}
public T GetChosenItem<T>() where T : Item
{
if(_fac.ContainsKey(typeof(T))
return _fac[typeof(T)];
return null;
}
}
Then in your interface instead of List<Item> ChosenItems you can do ChosenItemCollection ChosenItems.
Using this in your example :
GreedyItem item = // ...
ItemContainer.ChosenItems.Add(item);
ItemContainer.ChosenItem.ChosenItem<GreedyItem>();
I think Pidon has a nice solution. But could result in a runtime error when using not implemented Item derives.
Another solution could be adding properties which will do the casts to the implemented types:
public class ChosenItemsContainer : IItemContainer<FabulousItem>, IItemContainer<NiceItem>, IItemContainer<GreedyItem>
{
// these properties are only visible when casting to the correct
// interface. Which the public properties below will do.
FabulousItem IItemContainer<FabulousItem>.ChosenItem { get; set; }
GreedyItem IItemContainer<GreedyItem>.ChosenItem { get; set; }
NiceItem IItemContainer<NiceItem>.ChosenItem { get; set; }
// return this as IItemContainer<FabulousItem>
public IItemContainer<FabulousItem> AsFabulous
{
get
{
return (IItemContainer<FabulousItem>)this;
}
}
// return this as IItemContainer<NiceItem>
public IItemContainer<NiceItem> AsNice
{
get
{
return (IItemContainer<NiceItem>)this;
}
}
// return this as IItemContainer<GreedyItem>
public IItemContainer<GreedyItem> AsGreedy
{
get
{
return (IItemContainer<GreedyItem>)this;
}
}
}
ChosenItemsContainer container = new ChosenItemsContainer();
container.AsFabulous.ChosenItem = new FabulousItem();
container.AsNice.ChosenItem = new NiceItem();
container.AsGreedy.ChosenItem = new GreedyItem();
This way each implemented type has it's own ChosenItem instance. I think this is a clean solution without cluttering of generic <T> in code.
I have an arbitrary amount of classes, classThatInherits, anotherClassThatInherits, etc. that inherit classToBeInherited.
I then have a method, b, that needs to be able to access myValue from the classes that inherit classToBeInherited. How can I achieve this, without casting?
//This class will be inherited by other classes
public class classToBeInherited {
public bool isSomething { get; set; }
}
//This class with inherit 'classToBeInherited'
public class classThatInherits : classToBeInherited {
public int myValue { get; set; } //this needs to be accessable...
}
//...And so will this class
public class anotherClassThatInherits : classToBeInherited {
public int myValue { get; set; }
}
private class normalClass {
private void a() {
classThatInherits cti = new classThatInherits();
b(cti);
anotherClassThatInherits acti = new anotherClassThatInherits();
b(acti);
}
private void b(classToBeInherited c) {
//***
//get myValue from the classes that inherit classToBeInherited
//***
}
}
Move myValue to classToBeInherited:
public class classToBeInherited {
public bool isSomething { get; set; }
public abstract int myValue { get; set; }
}
Then in classThatInherits and anotherClassThatInherits use public override int myValue { get; set; } to implement that property.
Ofcorse, if myValue is needed in only some of the classes, then you can have virtual and not abstract property.
var a = c as anotherClassThatInherits;
if (a != null)
{
var myValue = a.myValue;
}
I don't know why you don't want to do casting, but it's very common to have code like above.
UPDATED
If you really don't want casting, you can use reflection (but you still need to know the type of anotherClassThatInherits)
var getter = typeof(anotherClassThatInherits).GetProperty("myValue").GetGetMethod();
var myValue = getter.Invoke(c, null);
I have the following design goal in a class hierarchy:
There is a BaseClass defining some properties, which would usually be read/write:
public class Media
{
public virtual object Content { get; set; }
public virtual double recordingLength { get; set; }
}
The intention is to have some subclasses where this property now is readonly:
public class CompactDisk : Media
{
public override object Content
{
get { return this.getContent(); }
set {
// THERE SHOULDN'T BE A SETTER
}
}
public override double recordingLength
{
get { return 74; }
set {
// NO SETTER EITHER HERE!
}
}
}
I'm lost here, because I don't know how should I implement my design intent.
One possible approach is using interfaces.
You can split your base concept into two interfaces:
public interface IWritableMedia
{
object Content { set; }
double recordingLength { set; }
}
public interface IReadOnlyMedia
{
object Content { get; }
double recordingLength { get; }
}
And then something like CompactDisk should only implement IReadOnlyMedia:
public class CompactDisk : IReadOnlyMedia
{
public object Content { get { return ......; } }
public double recordingLength { get { return .......; } }
}
If you want to implement a CD-RW (rewritable), you should implement both interfaces:
public class RewritableCompactDisk : IReadOnlyMedia, IWritableMedia
{
public object Content { get; set; }
public double recordingLength { get; set; }
}
This way you can type your variables as IReadOnlyMedia or IWritableMedia:
IReadOnlyMedia media = new CompactDisk();
IWritableMedia media2 = new RewritableCompactDisk();
Now the issue is IWritableMedia doesn't provide getters and you don't want to declare another variable of type IReadOnlyMedia. The solution is designing a third interface called IReadWriteMedia and RewritableCompactDisk should implement it:
public interface IReadWriteMedia : IReadOnlyMedia, IWritableMedia
{
}
public class RewritableCompactDisk : IReadWriteMedia
{
public object Content { get; set; }
public double recordingLength { get; set; }
}
Since IReadWriteMedia implements IReadOnlyMedia and IWritableMedia, now you'll be able to type variables with IReadWriteMedia and access both getters and setters:
IReadWriteMedia media3 = new RewritableCompactDisk();
object content = media3.Content;
media3.Content = "hello world";
You can't, or really shouldn't, have a design where the sub types "hide" functionality of the base type. You can:
In your setters throw a NotSupportedException, or similar. This is how the Stream class behaves when you try to set the length of a stream that cannot be set.
Change your design. I don't see a way to get properties working the way you want (without resorting to "hiding", which IMHO isn't a good solution), but perhaps something like this:
public interface IMedia
{
object Content { get; }
double RecordingLength { get; }
}
public interface IWritableMedia : IMedia
{
void SetContent(object content);
void SetRecordingLength(double length);
}
Your CompactDisk would implement the just the IMedia interface, whereas a HardDrive class may choose to implement the IWritableMedia interface.
I am having an issue with an explicit interface that I created and am getting the exception,
'x' does not contain a definition for 'y' and no extension method 'y' accepting a first argument of type 'x' could be found
I have a series of classes. The base class:
public interface IFactoryResponse
{
object instance { get; set; }
string instanceconfig { get; set; }
}
The class that explicitly implements it:
public class FactoryResponseImpl : IFactoryResponse
{
object IFactoryResponse.instance {
get { return ((IFactoryResponse)this).instance; }
set { ((IFactoryResponse)this).instance = value; }
}
string IFactoryResponse.instanceconfig {
get { return ((IFactoryResponse)this).instanceconfig; }
set { ((IFactoryResponse)this).instanceconfig = value; }
}
}
and in another class I get the above error. Visual studio can find the interface and class ok, but it can't resolve the instance property. What am I missing here. I am probably missing one of the more refined rules of explicit inheritance.
if (facconfig.useabstract) {
response.instance = Activator.CreateInstance(m_entassembly.GetType(entconfig.Classname, true, true));
response.instanceconfig = facconfig.config;
} else {
Assembly assem = Assembly.LoadFrom(facconfig.assemblyfile);
object Obj = Activator.CreateInstance(assem.GetType(facconfig.Classname, true, true));
response.instance = Obj;
response.instanceconfig = facconfig.config;
}
Your implementation is incorrect. It will cause StackOverflowException because property calls itself. You can easily implement the properties using autoproperties:
public class FactoryResponseImpl : IFactoryResponse
{
object IFactoryResponse.instance { get; set; }
string IFactoryResponse.instanceconfig { get; set; }
}
When interface member is implemented explicitly you have to look at variable as the interface, either by casting your class instance to that interface or assigning it into a variable types as that interface.
if (facconfig.useabstract) {
((IFactoryResponse)response).instance = Activator.CreateInstance(m_entassembly.GetType(entconfig.Classname, true, true));
((IFactoryResponse)response).instanceconfig = facconfig.config;
} else {
Assembly assem = Assembly.LoadFrom(facconfig.assemblyfile);
object Obj = Activator.CreateInstance(assem.GetType(facconfig.Classname, true, true));
((IFactoryResponse)response).instance = Obj;
((IFactoryResponse)response).instanceconfig = facconfig.config;
}
Why do you need the interface to be implemented explicitly? You shouldn't do that unless you have very good reason. With implicit implementation everything is much easier:
public class FactoryResponseImpl : IFactoryResponse
{
public object instance { get; set; }
public string instanceconfig { get; set; }
}
And your other code should work just fine.
Your explicit implementations are referencing themselves. You should be referencing a private field or the public implementation. E.g.:
public class FactoryResponseImpl : IFactoryResponse
{
DatabaseFactoryResponseInstance _instance;
public FactoryResponseImpl()
{
_instance = new DatabaseFactoryResponseInstance();
}
object IFactoryResponse.instance {
get { return (object)_instance; }
set {
if (value != null)
{
DatabaseFactoryResponseInstance dbInstance;
dbInstance = value as DatabaseFactoryResponseInstance;
if (dbInstance == null)
throw new InvalidOperationException();
_instance = dbInstance;
}
}
}
Is this what you where aiming for?
public interface IFactoryResponse
{
object instance { get; set; }
string instanceconfig { get; set; }
}
public class FactoryResponseImpl : IFactoryResponse
{
object IFactoryResponse.instance { get; set; }
string IFactoryResponse.instanceconfig { get; set; }
}
class Test
{
public void TestMethod()
{
IFactoryResponse response = new FactoryResponseImpl();
response.instance = null;
}
}
If one uses explicit interface implementations like IFactoryResponse.instance, then these methods are not publicly visible. Either you need to cast to IFactoryResponse to access them or define the methods as public: public object instance { ... }.