Here`s the question.
public abstract class A {}
public class B:A
{
public TypeF FieldB;
}
public class C:A
{
public TypeG FieldC;
}
public class TypeF:A { }
public class TypeG:A { }
I want to have interface ex: ITypeFG and to implement it in B and C BUT to have properties names FieldB and FieldC
interface ITypeFG
{
public A FieldFG; //But i want to have names TypeF in A and TypeG in B
}
Can this be done?
Thanks.
explicit interface implementation:
public class B : A, ITypeFG
{
public TypeF FieldB { get; set; } // please don't expose public fields...
A ITypeFG.FieldFG { get { return FieldB; } }
}
public class C : A, ITypeFG
{
public TypeG FieldC { get; set; }
A ITypeFG.FieldFG { get { return FieldC; } }
}
Note that if the interface has a setter, you'll need to cast:
public class B : A, ITypeFG
{
public TypeF FieldB { get; set; }
A ITypeFG.FieldFG { get { return FieldB; } set { FieldB = (TypeF)value; } }
}
public class C : A, ITypeFG
{
public TypeG FieldC { get; set; }
A ITypeFG.FieldFG { get { return FieldC; } set { FieldC = (TypeG)value; } }
}
Two points:
Interfaces in C# can't have fields, but they can have properties.
The desired feature isn't sensible: if clients would always have to know the "specific" name of the implemented interface-property to interact with an implementation, then it isn't much of an interface is it - it's little more than a marker.
As Marc Gravell suggests, a decent workaround is to use explicit implementations. If the client has a reference to the implementing object typed as the interface, they can use the "general" name of the property. If they have a specific reference (i.e. typed as the implementing type) , they can use the "specific" name (and won't be confused by the general name since they won't see it on IntelliSense, for example).
Sounds like you should treat the field names as data along with A. That way you can keep a common interface and only vary the content of what is returned:
class Data
{
public string Name {get;set;}
public A Value {get;set;}
}
interface ITypeFG
{
Data Field {get;}
}
class B : A, ITypeFG
{
public Data Field
{
get
{
return new Data {Name = "TypeF", Value = FieldB};
}
}
}
class C : A, ITypeFG
{
public Data Field
{
get
{
return new Data {Name = "TypeG", Value = FieldC};
}
}
}
Related
In order to make an export, I need to overload an object in order to add a property which will transform a property from master class :
public class A
{
public int MyProperty1 { get; set; };
public int MyProperty2 { get; set; };
/*...*/
public myType MyPropertyN { get; set; };
}
public class B : A
{
public override string MyProperty1
{
get :
{
return A.MyProperty1.ToString();
}
set :
{
a.MyProperty1 = int.parse(value);
}
}
}
The problem is my A objects are already instantiated because the model come from the database.
I'm looking for a solution where I can do something like this :
var List<A> myListOfA = PopulateFromSomewhere();
var List<B> myListOfB = myListOfA.Select(x => new B(x)).ToList();
Where A will be copied in B and after call B in my export. I don't want to copy manually all properties of A in the constructor of B. Some objects have more than 20 properties.
Most of the time changing the return-type from a class is a sign of a bad design. In particular it means that you should favour composition over inheritance.
Having said this what you actuall want is to map one class to another. You can do that yourself, e.g. like this:
class A
{
int MyProperty { get; set; }
}
class B
{
private readonly A a;
public B(A a) { this.a = a; }
}
Now you can easily implement your mapping:
class B
{
public string MyProperty
{
get => this.a.MyProperty.ToString();
set => { this.a.MyProperty = int.Parse(value); } // consider to check the value before conversion
}
}
This is just the basic idea. As your models can become huge and doing this mapping yourself therefor becomes pretty cumbersome, you'd best use some automatic mapper, e.g. AutoMapper for that.
Suppose I have two classes and both contain the same fields
Class A
{
public string Name { get; set; }
public int Designaton { get; set; }
}
Class B
{
public string Name { get; set; }
public int Designation { get; set; }
}
And I have one interface and two classes which are inherited from interface
public interface IDeprt
{
object BindData();
}
And two extractor classes:
public classAItem : IDeprt
{
public object BindData()
{
return new A()
{
// mapping operation
}
}
}
public classBItem : IDeprt
{
public object BindData()
{
return new B()
{
//same mapping operation
}
}
}
My question, how can I implement this in generic way using <T> .
Both classes are doing same operation only return type change. If I am doing in the above way there is lot of duplication of code.
Make your ITem interface and also BindData generic make them use the same generic parameter.
public interface IItem<T>
{
T BindData();
}
Then implement the subclasses like below :
public class AItem : ITem<A>
{
public A BindData(){
return new A(){
// mapping operation
}
}
}
public class BItem : ITem<B>
{
public B BindData(){
return new B(){
//same mapping operation
}
}
}
Edit : As the question evolves.
Make a shared base class for A and B classes.
public abstract class CommonItem
{
public string Name { get; set; }
public int Designaton { get; set; }
}
class A : CommonItem
{
}
class B : CommonItem
{
}
Then make class with a method that accepts a generic parameter with new and CommonItem constraints.
public class Binder
{
public T BindData<T>() where T: CommonItem, new()
{
return new T()
{
// you can access the properties defined in ICommonItem
}
}
}
Usage :
var binder = new Binder();
var boundA = binder.BindData<A>();
var boundB = binder.BindData<B>();
I need to have a list where all items extend class A and implement interface I. Additionally class A might be multiple parents up in the hierarchy.
If all the classes were direct descendants of class A I could just use an Abstract class that implements I as the generic and use that, but my use case doesn't allow for this.
is there a way to tell a List that its elements must both extend class A and implement interface I ? List<A,I> ? If not is there another way around this?
Example Code:
public class A
{
// Class belongs to a third party library
}
public class B : A
{
// Class belongs to a third party library
public string Text{ get; set; }
}
public class C : A
{
// Class belongs to a third party library
public string Other{ get; set; }
}
interface I
{
// Belongs to me
bool shouldSend();
string getName();
string getValue();
}
public class MyClass : B, I
{
public string Name{ get; set; }
public function myClass(ObjectWithName obj)
{
Name = obj.Name;
}
public string getValue()
{
return Text;
}
public bool shouldSend()
{
return true;
}
}
public class MyClass2 : C, I
{
public string Name{ get; set; }
public function myClass(ObjectWithName obj)
{
Name = obj.Name;
}
public string getValue()
{
return Other;
}
public bool shouldSend()
{
return true;
}
}
public class mainActions
{
// Here is where I need the list to use both restrictions
public List<A,I> myList;
// The class I need to use these things in
public function mainActions(List<ObjectWithName> elements)
{
ThirdPartyCollection TPC = new ThirdPartyCollection();
foreach(var el in elements)
{
MyList.Add(new MyClass(el));
MyList.Add(new MyClass2(el));
// TPC.Add accepts implementations of A here
TPC.Add(MyList.ElementAt(MyList.Count - 1));
TPC.Add(MyList.ElementAt(MyList.Count - 2));
}
}
public function doThisLater()
{
foreach(var el in myList)
{
if(el.shouldSend())
{
// I need an implementation of I here
doSomethingElse(el.getName(), el.getValue());
}
}
}
}
EDIT: For anyone coming in search of an answer here in the future, it doesn't seem to be possible. Instead I used #servys answer and made a new list to hold my sub class objects:
public class MyList<T> : List<T> where T : A, I
{
}
Then I kept different lists for each subclass:
protected MyList<MyClass> MCList = new MyList<MyClass>();
protected MyList<MyClass2> MCList2 = new MyList<MyClass2>();
When you specify generic constraints you can specify as many as you want, and all of them must be met, so you can simply add a generic constraint of A and I to your type, and a type has to meet both of those constraints to be a valid generic argument.
public class ClassThatNeedsABetterName<T> : List<T>
where T : A, I
{ }
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.
Ok, so C# has properties
public int Prop {get;set;}
I can put the getter and the setter on separate interfaces like this:
public interface IRead
{ int AnInt { get; } }
public interface IWrite
{ int AnInt { set; } }
And then mix and match them like so:
public class WorkingClass : IRead, IWrite
{
public int AnInt { get; set; }
}
Where it starts to go wrong is where I might have a base object.
public class BaseClass : IRead
{
private int _anInt;
public BaseClass(int anInt)
{ _anInt = anInt; }
public virtual int AnInt
{ get { return _anInt; } }
}
I then want a derived class which can write as well.
public class Derived : BaseClass, IWrite //bits elided
{
public override int AnInt
{
get { return base.AnInt; }
set { throw new NotImplementedException(); } //<-- error
}
}
Which of course doesn't work.
This actually doesn't come up that often. I prefer to have methods with change state and have properties read only. This is design 101 I guess, but as a contrived example, I'd have an Age property with just a get and then a method called IncreaseAge.
So with that all in mind. If you did want to have a mutable object with seperate read and write interfaces how would you do it?
I could do it in a Java-esque way with separate getter/setter methods on each interface. But that negates the benefits of properties + one of the cop programs will yell at me.
You can have the base setter protected and have the derived class implement IWrite explicitly delegating to the base setter:
public class BaseClass : IRead {
public BaseClass(int anInt) { AnInt = anInt; }
public int AnInt {
get; protected set;
}
}
public class Derived : BaseClass, IWrite {
public Derived(int anInt) : base(anInt) { }
int IWrite.AnInt {
set { base.AnInt = value; }
}
}
(The keyword base can even be omitted and the base property doesn't need to be virtual.)