I'm working on a project which needs to determine the type of an object, take the information from that type and move it to a structure that fits in our database.
For this, I'm using Pattern Matching with a case statement which works fine.
The only thing that I got stuck with is that some types have nested types as well. The information in those nested types is the information that I need.
Take a look at the code below:
public class CallAnswered
{
public string Caller { get; set; }
public MetaDataInformation MetaData{ get; set; }
}
public class CallAbandoned
{
public string ReasonForAbandonment{ get; set; }
public MetaDataInformation MetaData { get; set; }
}
public class MetaDataInformation
{
public DateTime ReceivedAt { get; set; }
public DateTime AnsweredAt { get; set; }
}
public void DetermineType<T>(T callEvent)
{
switch (callEvent)
{
case CallAnswered callAnswered:
case CallAbandoned callAbandoned:
// Somehow, I need to access the "MetaData" property as a type
break;
}
}
Like shown in the code above, I am able to detect the parent type and assign it a variable. Bu I have no clue on how to get the nested MetaDataInformation type.
Does anyone have an idea how this can be resolved?
You do not need a generic type here. By deriving from an abstract base class, you can solve two problems.
You can use the base type instead of the generic type and access all the public members of this base class.
You can add an abstract method in the base class implemented in the two derived classes making the switch statement obsolete.
public abstract class Call
{
public MetaDataInformation MetaData { get; set; }
public abstract void Process();
}
public class CallAnswered : Call
{
public string Caller { get; set; }
public override void Process()
{
// TODO: Do Answer things. You can access MetaData here.
}
}
public class CallAbandoned : Call
{
public string ReasonForAbandonment{ get; set; }
public override void Process()
{
// TODO: Do Abandonment things. You can access MetaData here.
}
}
somewhere else
public void ProcessCalls(Call callEvent)
{
// Replaces switch statement and does the right thing for both types of calls:
callEvent.Process();
}
This is called a polymorphic behavior.
See also:
Polymorphism (Wikikpedia)
Polymorphism (Microsoft Docs)
Related
I am having trouble understanding the proper use of base and this within an inherited get method. I have an interface IMatchModel:
public interface IMatchModel
{
int TypeId { get; }
DateTime DataDate { get; set; }
string TypeName { get; set; }
}
And a base model class TradeModel:
public class TradeModel
{
public long TradeId { get; set; }
public DateTime DataDate { get; set; }
public string TradeName { get; set; }
}
Then I have a class that inherits from TradeModel and implements IMatchModel. I am currently using the following method:
public class TradeMatchModel : TradeModel, IMatchModel
{
public int TypeId { get { return 1; } }
public string TypeName
{
get
{
return base.TradeName;
}
set
{
base.TradeName = value;
}
}
}
The TradeModel class is used within a function that operates on all of its attributes. IMatchModel is used in a function that only needs the attributes contained in the interface. The code works properly, but I still feel like I don't quite understand if it is best to be using base over this. Is the use of base in this context incorrect?
The only time you need to use base is when you are inside a overridden virtual method and you need to call the base implementation of the method you are currently overriding. All other times you can use this..
Also this. is generally not needed unless you have a name conflict between a field or property in the class and a name of a variable or a parameter. 99% of the time you can just leave off the this. and do return TradeName;
I have an Interface for a master-detail common interface hierarchy:
public interface ITModel
{
ITPeriodHead[] PeriodHeads { get; set; }
}
I try to use it this way:
public class T19Model:ITModel
{
public T19Item[] Items { get; set; }
**public T19PeriodHead[] PeriodHeads { get; set; }**
}
The array of PeriodHeads causes error at compile time,
despite T19PeriodHead implements ITPeriodHead, like this:
public class T19PeriodHead : BaseTPeriodHead, ITPeriodHead
{ ...
What is the solution? If I use the array of ITPeriodHead, I will not be able to access the periodhead items members, properties, methods....
Any help is appriciated.
You have to honor the interface contract. You are returning a more specific class that the interface defines, so you are not fully defining the interface.
You could explicitly implement the interface, but you have an issue with the setter - what if someone tries to set the property to an array of objects that are not T19PeriodHeads?:
public class T19Model:ITModel
{
public T19Item[] Items { get; set; }
public T19PeriodHead[] PeriodHeads { get; set; }
ITPeriodHead[] ITModel.PeriodHeads
{
get {return PeriodHeads;}
set {/* what to do here if value is not an array of T19PeriodHeads? */}
}
}
If you do not need a setter for the array property (maybe an Add method instead?) then you are fine.
I have a weird scenario that I can't seem to wrap my head around. I have the following base class:
public class Note
{
public Guid Id { get; set; }
public string SenderId { get; set; }
...
}
Which is then derived by the following class:
public class NoteAttachment : Note
{
public string FileType { get; set; }
public string MD5 { get; set; }
...
}
I use these classes to communicate with a server, through a generic wrapper:
public class DataRequest<T> : DataRequest
{
public T Data { get; set; }
}
public class DataRequest
{
public string SomeField { get; set; }
public string AnotherField { get; set; }
}
So I have a NoteAttachment sent to the method, but I need to wrap a Note object to send to the server. So I have the following extension method:
public static DataRequest<T> GetDataRequest<T>(this T data)
{
DataRequest<T> dataRequest = new DataRequest<T>
{
SomeField = "Some Value",
AnotherField = "AnotherValue",
Data = data
};
return dataRequest;
}
Now the problem. Calling the extension method in the following way works fine, however even though the DataRequest type is DataRequest<Note>, the Data field is of type NoteAttachment.
var noteAttachment = new NoteAttachment();
...
Note note = (Note)noteAttachment;
var dataRequest = note.GetDataRequest();
Debug.WriteLine(dataRequest.GetType()); //MyProject.DataRequest`1[MyProject.Note]
Debug.WriteLine(dataRequest.Data.GetType()); //MyProject.NoteAttachment <--WHY?!
What am I doing wrong?
You are mixing two things: run-time type of an object and compile type of a field.
Type of Data field is still Note. You can verify for yourself with reflection. For example, the following will print "Note":
Console.Write(
typeof(DataRequest<Note>).GetProperty("Data").PropertyType.Name);
The Type of the object that this field contains can be Note or any derived type. Assigning an object to the variable of a base class does not change its run-time class. And since GetType() returns the type of an object you get the actual derived type (NoteAttachment).
As #Alexi answered your first question, ill try the second question in the comment. Add a KnownType attribute to your note class like this:
[KnownType(typeof(NoteAttachment)]
public class Note
I want to create a class that can take different types of value in a property. I am trying to do this using polymorphism, but I am not still learning how to do this properly, hence my request for advice.
I have a base class and two classes that inherit from it:
public abstract class BaseClass
{
public string Name { get; set; }
public Unit Unit { get; set; }
}
public class DerivedClassFloat : BaseClass
{
public float Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
All is good, I can create a List and add different specialized subclasses. My problem comes when I need change the values of the items in my list:
foreach (var item in ListOfBaseClasses)
{
if(item is DerivedClassFloat)
((DerivedClassFloat) item).Value = float.NaN;
if (item is DerivedClassString)
((DerivedClassString) item).Value = string.Empty;
}
According to what I have read, that looks like a code smell. Is there a better way to access the value property of my derived classes based on the type I am trying to assign?
What about when you want to create the right subclass based on the value?
BaseClass newClass = null;
if (phenotype is DerivedClassFloat)
newClass = new DerivedClassFloat(){Value = 12.2};
if (phenotype is DerivedClassString)
newClass = new DerivedClassString(){Value = "Hello"};
I read about overriding virtual methods, but that works if I want to process the value, not to add or change it … maybe I am missing something?
I should make this more concrete, my apologies, I am not used to post question in this great site.
I need a property that is made of a list of attributes. Each attribute has a name and a value, but the value can be of different types. For example:
public class Organism
{
public string Name { get; set; }
public List<Attribute> Attributes { get; set; }
}
public class Attribute
{
public string AttributeName { get; set; }
public object AttributeValue { get; set; }
}
For a given organism I can have several attributes holding different value types. I wanted to avoid using the object type so that I don’t have to cast to the right type. I though property polymorphism was the solution to handle this case elegantly, but then I found myself using If ..Then which didn’t seem too different from casting in the first place.
If in your particular case you want to reset Value, you can define an abstract ResetValue method in the base class, which will be implemented by the derives classes.
As for your second case, you should check out Creational Design Patterns, and specifically the Factory and Prototype design patterns.
You can use generics to define the type and the implementing subclass will set the Value type to the type constraint:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedFloat : BaseClass<float> {}
public class DerivedString : BaseClass<string> {}
You can use Generics for this particular case:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
}
public class DerivedClassFloat : BaseClass<float>
{
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass<string>
{
public override string ToString()
{
return Value;
}
}
Polymorphic behaviour works on abstraction. Based on what your trying to do, you can reduce code smell to moving as much of your variability in code to base classess.
i would suggest is instead of property write method like as follows. You can something like as follows.
public void setValue(string val, Type type);//move this to your base class
Class MyValue{
private string strVal;
private int intVal;
//constructor
MyValue(string val, Type type){
//check the type enum here and set the values accordingly
}
}
then when set values
foreach (var item in ListOfBaseClasses)
{
item.setValue = MyValue("",Type.INT);
}
I'm not quite sure what you are trying to achieve with this approach - the Value properties are not of the same type, there is also no Value property on the base class which suggests that other types derived from the base class might not have it at all.
If all of your classes require a Value property, then maybe it should be of the most general type object - you could put it onto the base class, but that would require casting the values in the derived classes.
But then you could have a NullObject to represent an absence of value that you could assign to the Value property for every derived class.
You can use the abstract factory pattern. Consider this example:
// Base class
class Button
{
protected Button()
{
}
public string Name { get; set; }
}
// Factory interface
public interface ButtonFactory
{
Button CreateButton();
}
// And the concrete classes
class WindowsButton : Button
{
// ...
}
class WindowsButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new WindowsButton();
}
}
class MacButton : Button
{
// ...
}
class MacButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new MacButton();
}
}
Furthermore, you can combine the abstract factory pattern with the strategy pattern to encapsulate the custom behaviors that change with type.
I'd like to have the following setup:
class Descriptor
{
public string Name { get; private set; }
public IList<Parameter> Parameters { get; private set; } // Set to ReadOnlyCollection
private Descrtiptor() { }
public Descriptor GetByName(string Name) { // Magic here, caching, loading, parsing, etc. }
}
class Parameter
{
public string Name { get; private set; }
public string Valuie { get; private set; }
}
The whole structure will be read-only once loaded from an XML file. I'd like to make it so, that only the Descriptor class can instantiate a Parameter.
One way to do this would be to make an IParameter interface and then make Parameter class private in the Descriptor class, but in real-world usage the Parameter will have several properties, and I'd like to avoid redefining them twice.
Is this somehow possible?
Make it a private nested class that implements a particular interface. Then, only the outer class can instantiate it, but anyone can consume it (through the interface). Example:
interface IParameter
{
string Name { get; }
string Value { get; }
}
class Descriptor
{
public string Name { get; private set; }
public IList<IParameter> Parameters { get; private set; }
private Descriptor() { }
public Descriptor GetByName(string Name) { ... }
class Parameter : IParameter
{
public string Name { get; private set; }
public string Value { get; private set; }
}
}
If you really must avoid the interface, you can create a public abstract class that has all of the properties but declares a protected constructor. You can then create a private nested class that inherits from the public abstract that can only be created by the outer class and return instances of it as the base type. Example:
public abstract AbstractParameter
{
public string Name { get; protected set; }
public string Value { get; protected set; }
}
class Descriptor
{
public string Name { get; private set; }
public IList<AbstractParameter> Parameters { get; private set; }
private Descriptor() { }
public Descriptor GetByName(string Name) { ... }
private class NestedParameter : AbstractParameter
{
public NestedParameter() { /* whatever goes here */ }
}
}
LBushkin has the right idea. If you want to avoid having to retype all the properties just right-click the name of the class and choose "Refactor" > "Extract Interface", that should give you an interface that contains all those properties. (This works in VS 2008, I don't know about earlier versions.)
C# generally takes the approach that instead of avoiding redundant code, VS will just help you write it faster.
You could use a constructor marked Internal.
That way it's public to classes in the assembly, and private to classes outside of it.
Mark the class to be "protected" from instantiation (Parameter) with the StrongNameIdentityPermission attribute and the SecurityAction.LinkDemand option:
[StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey="...")]
class Parameter
{
...
}
You will need to provide the appropriate public key. Because you are demanding a link-time (JIT-time, in fact) check on the Parameterclass, this means that it can only be used from an assembly that is signed with a strong name that uses the private key matching the public key that you supply in the attribute constructor above. Of course, you will need to put the Descriptor class in a separate assembly and give it a strong name accordingly.
I have used this technique in a couple of applications and it worked very well.
Hope this helps.
If you want only the Descriptor class to instantiate a Parameter, then you can make the Descriptor class a nested class of Parameter. (NOT the other way around) This is counterintuitive as the container or parent class is the nested class.
public class Parameter
{
private Parameter() { }
public string Name { get; private set; }
public string Value { get; private set; }
public static Parameter.Descriptor GetDescriptorByName(string Name)
{
return Parameter.Descriptor.GetByName(Name);
}
public class Descriptor
{ // Only class with access to private Parameter constructor
private Descriptor() { // Initialize Parameters }
public IList<Parameter> Parameters { get; private set; } // Set to ReadOnlyCollection
public string Name { get; private set; }
public static Descriptor GetByName(string Name) { // Magic here, caching, loading, parsing, etc. }
}
}
There is another way: check the call stack for the calling type.