Initialise one object from another where they share a common interface c# - c#

I want to pass in an instance of an interface to an object and initialise all the values of this object to those of the object passed in where both objects implement the same interface? Are there any good shortcuts in this particular case where they share an interface. It seems to me there must be... I just can't recall ...
EDIT: After John's feedback, the question is better expressed as - How do I pass in an instance of an interface to an object's constructor and initialise all the values of this object to those of the interface instance passed in?
Most deep copying solutions (including my own previous solutions) return an object - which is not going to work in a constructor, or rely upon creating a new instance (which is not going to work with an interface as the source and destination).
I want to pass in both source and destination and have properties of the source copied to the destination where they are both interfaces. Is there an existing solution for this. Or do I revisit my own code and try to adapt it - my previous own solution from 2009 (with minor bug corrected in the answers) SetValue on PropertyInfo instance error "Object does not match target type" c# AND svics answer in transfering one object properties values to another one suffice for the simple cases where all properties are just values.
e.g.
public interface ISomething
{
...
}
public class A : ISomething
{
public A(ISomething input)
{
// what goes here??
}
}

I'm not really sure I fully understand your restrictions, but for most object copying work I use AutoMapper, which greatly helps with the grunt work of copying objects. It means a different approach than copying properties in constructors, but maybe useful. Here's some example code:
public interface ISomething {
string MyProperty { get; set; }
int AnotherProperty { get; set; }
B ClassProperty { get; set; }
}
public class A : ISomething {
public string MyProperty { get; set; }
public int AnotherProperty { get; set; }
public B ClassProperty { get; set; }
}
public class B {
public string BProperty_1 { get; set; }
public int BProperty_2 { get; set; }
}
class Program {
static void Main(string[] args) {
// Configure the mapping
Mapper.Initialize(cfg => cfg.CreateMap<ISomething, ISomething>());
// Initialize first instance
var firstA = new A {
MyProperty = "Test",
AnotherProperty = 21,
ClassProperty = new B {
BProperty_1 = "B String",
BProperty_2 = 555
}
};
// Initialize second instance and perform the mapping
var secondA = Mapper.Map<ISomething>(firstA);
Here, all the properties in firstA are copied over to secondA, including the properties in ClassProperty.
The mapping configuration is performed once on startup, and uses recursion and reflection to build the mapping model. It can then be used anywhere in your code. If new properties are added to the interface, the mapping configuration stays the same.

Simply set all the properties of the interface in the constructor:
public class A : ISomething
{
public A(ISomething input)
{
A.MyProperty = input.MyProperty;
A.AnotherProperty = somethingNotFromTheInterface
}
}
This is called a copy-constructor. Wheather this actually creates a deep or a shallow copy of your existing instance depends on if it contains references to other reference-types. In this case you´d have to re-create all those instances also:
public A(ISomething input)
{
A.MyProperty = new MyType(input.MyProperty);
A.AnotherProperty = somethingNotFromTheInterface
}
Which itself assumes you hacve a copy-constructor for the type of MyProperty also.
This can become some huge task when your interface is quite big. You may consider looping all the interfaces properties with reflection in this case, or even better rethink if your interface is actually serving a single purpose and not doing too much.

Related

Inheritance depending on calculated attribute

I am curently working on a small project (C#) where I have data to analyse.
To do so, I pass the data into the constructor of a class.
The class makes a first analysis on the data, and a certain value is determined using the data. Using this value I can say that this data is of Type B, C, D, ... and the analysis would continue in another class corresponding to the data type.
This would be it's class diagram representation :
So the "Data" Class should abstract but not really ? ¯\_(ツ)_/¯
I did some reasearch about the factory design pattern, but I think this is not really what I am trying to achieve. Is there maybe an other design pattern that does what I want to do?
Thank you for helping.
If I understand you correctly, you want the base class to determine which child class to create based on the data passed into the constructor. If so, you can't do it that way - a class cannot change itself to be a different/derived type when being constructed.
I assume that all the data types have some common properties and so you decided to put those common properties in a base class. I also assume you don't want each data type child class to have redundant code setting those common properties in the base class. You accomplish that by having the child class call a method in the base class, passing the data. You can do this in the constructors if you wish. For example:
class BaseData
{
BaseData(Dictionary<string,string> data)
{
this.CommonProp1 = data["CommonProp1"];
this.CommonProp2 = data["CommonProp2"];
}
public string CommonProp1 { get; set; }
public string CommonProp2 { get; set; }
}
class DataTypeA : BaseData
{
DataTypeA(Dictionary<string,string> data)
: base(data) // <-- magic here
{
this.TypeA_Prop1 = data["TypeA_Prop1"];
this.TypeA_Prop2 = data["TypeA_Prop2"];
}
public string TypeA_Prop1 { get; set; }
public string TypeA_Prop2 { get; set; }
}
I believe the factory pattern actually is what you want since you want to create an instance of a class in which the type is determined at run time. This is where you encapsulate the code that determines which type of child class to create. Something like:
class DataFactory
{
public static BaseData BuildDataClass(byte[] serializedData)
{
Dictionary<string,string> data = ParseData(serializedData);
switch (data["DataType"])
{
case "TypeA":
return new DataTypeA(data);
default:
return null;
}
}
private static Dictionary<string,string> ParseData(byte[] serializedData)
{
var data = new Dictionary<string, string>();
// bla bla
return data;
}
}

C# How to return an instance of the type of subclass from function?

I have a bunch of classes that formulate various variations of items. I currently have a class like this:
public class Item {
public ItemFile file { get; set;}
public ItemCalendar calendar { get; set;}
public ItemWebsite website { get; set;}
}
ItemFile etc are classes made using Entity Framework and map to the database tables that provide the information relating to that type of item. The item class only has one of the internal properties actually instantiated.
I can see the number of items growing to around 25 or more. I don't feel right making the view model containing 25 properties where 24 of them are null with only one being not null.
I want something that can work with entity framework and return a class that can return only it's actual type. Therefore if I ask for the variation of the item I would get back ItemFile for files and ItemCalendar for calendars.
I've tried something like this:
public class Item
{
public ItemBase item { get; set; }
}
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
But then I don't know how to return ItemFile as public typeName is an error.
I then tried:
public class Item
{
public ItemBase<ItemFile> item { get; set; }
}
public class ItemBase<T>
{
public T ItemInstance { get; set; }
}
But to get that to work, I had to hardcore FileItem in the <> on the item class which goes back into knowing the type before hand.
Is there anyway to get this to work? Bonus points if it can work with entity framework as I'm pulling back the classes from there. Worst comes to worst if it doesn't work entity framework wise is I can pull it all and then convert it into the form that answers the question.
If the title of the question is wrong, feel free to edit. I wasn't sure how to ask.
tl;dr version: I want to be able to return multiple types of classes from a function using a type that is passed in not using <>.
Edit 1:
I forgot to show my inheritence example. I've tried this but also got stuck with something similar to the above.
public class ItemBase
{
public Type typeName { get; set; }
public object ItemInstance { get; set; }
public typeName GetInstance()
{
return Convert.ChangeType(ItemInstance, typeName);
}
}
public class ItemFile : ItemBase
{
public String FileName { get; set; }
}
public class Test
{
public void testFunction()
{
//Made this just so the compiler didn't complain.
ItemFile testFile = new ItemFile();
//I can use a function to get the item base.
ItemBase baseItem = testFile;
//How do I do this? Use a function to get the ItemFile from the instance.
ItemFile finalItem = baseItem.GetInstance();
}
}
I want to be able to return multiple types of classes from a function using a type that is passed in not using <>.
<> (generics) are the mechanism by which a function can explicitly return more than one type. Without generics the function returns whatever type it says it returns.
object SomeFunction() // Returns an object
ItemBase SomeOtherFunction () // returns ItemBase
In the above examples, SomeFunction can still return any type (because all types inherit from object.) But it won't be explicit. All you know for sure is that it's an object.
Similarly, SomeOtherFunction can return an ItemBase or any class that inherits from ItemBase. But that's all you know about it.
Ideally you don't want to have functions returning one type (like object or ItemBase) and then cast the result of the function to another more specific type. The function should return what you want, and you should want what the function returns. Generics help with that. For example:
public TItem Instance<TItem>() where TItem : ItemBase
allows a function to return a specified type as long as it is an ItemBase or inherits from one.
This last comment is going to seem odd or useless but it's the truth. If you find yourself in a scenario where the above rules don't work and you need to be able to do something that you can't do or shouldn't do, go back and rethink why you're trying to do that. That's where the real problem is.
That means you probably need to go back a step and get yourself out of the situation where you're trying to work against the language. What are you trying to accomplish and how can you do it in a way that works with the language, not against it?
I believe this is about as close as you're going to get.
using System;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
EFTypeData itemData = GetItemData();
var asmName = Assembly.GetExecutingAssembly().GetName().Name;
var type = Type.GetType($"ConsoleApplication1.{itemData.TypeName}, {asmName}");
var instance = Activator.CreateInstance(type);
var item = new Item<Object>()
{
ItemBase = instance
};
}
private static EFTypeData GetItemData()
{
return new EFTypeData() { TypeName = "ItemFile" };
}
}
class EFTypeData
{
public string TypeName { get; set; }
}
class Item<T> where T: class
{
public T ItemBase { get; set; }
}
class ItemFile
{
public string FileName { get; set; }
}
}
This will, given a string "ItemFile", create an instance and assign it to Item. If you run this and inspect item, you have
The big caveat to this is that at compile-time, all you have is an Object as your ItemBase. And without hard-coding your Type (i.e. var item = new Item<ItemFile>();), you're never going to know more.
That said, with this method you are perfectly clear to iterate over fields and such using Reflection. But this is a limitation of this level of run-time object manipulation.

Abstract class with class typed properties

I'm deserializing some JSON responses and putting them into one of two primary classes depending on if a single object is returned or if a list of objects is returned. I'm currently using
public class MultiResponse
{
public List<DeserializedResult> Result { get; set; }
}
public class SingleResponse
{
public DeserializedResult Result { get; set; }
}
public class DeserializedResult
{
public string Id { get; set; }
public string AccountName { get; set; }
}
to contain the response(s). However I know it's not the best way, especially since I'm having to use a dynamic return in the calling class to deal with the two types of responses possible. I think an abstract class (or interface?) is a better way to do this, but I don't know how to implement it. Am I on the right track & if so, how do I construct the abstract class and do the inheritance?
Create a design based on multi responses - i.e. holding / returning a list even if when there is only one object. It eliminates the design "hint" that there is a special case somehow. And The resulting code will be more consistent and robust.
The focus should be on the object itself - what you do with it after re-hydration. Not on the trivial happenstance that I have one object or more than one. That distinction is no different that "4 objects or not 4 objects."
Abstracting the container to a single class necessarily makes working with the objects the focus, the emphasis of your design.
edit
Think of it this way. Single or multiple deserialized objects is a consequence of how many objects there were to deserialize. It is an implementation detail not germane to the (deserialized) objects actual use. Encapsulate implementation details, that is, hide them from the client code. Give clients classes and methods that express functionality in "business domain" terms.
end edit
Edit
... I'm having to use a dynamic return in the calling class to deal with the two types of responses possible. I think an abstract class (or interface?) is a better way to do this, but I don't know how to implement it.
Main points:
ClientApi transforms the deserialized object to the desired class.
Two API's!
constructors called by the de-hydrating object
Hide the default constructor to ensure valid object instantiation
GetDeHydratedJsonThingy called by the "using" client.
Deserializer and "using" client are decoupled thanks to the ClientApi class.
De-hydration works with DeserializedResults objects
"Using" client only cares about MultipleResponse objects
"using" client deals with only one return type.
P.S. After I wrote this I realized only one "Response" class is needed, now that ClientApi class encapsulates the object instantiations. Commented out code is original.
P.P.S. My method and parameter names are really lousy. Use names that have meaning in the problem domain. i.e. user's terminology.
.
public class ClientApi {
protected MultiResponse MoreThanOne { get; set; }
// protected SingleResponse OnlyOne { get; set; }
protected ClientApi ( );
public ClientApi (List<DeserializedResult> theList) {
if (theList == null) throw ArgumentNullException("error message here");
// add overloaded constructors to MultiResponse class.
MoreThanOne = new MultiResponse (theList);
// OnlyOne = null;
}
public ClientApi (DeserializedResult onlyOne)
if (onlyOne == null) throw ArgumentNullException("error message here");
MoreThanOne = new MultiResponse(onlyOne);
// OnlyOne = onlyOne;
}
///<summary>
/// Always returns an object. The list may be empty,
/// but never null
///</summary>
public MultiResponse GetDeHydratedJsonThingy() {
MultiResponse HereYaGo = new MultiResponse();
// if (MoreThanOne !=null) HereYaGo.AddRange(MoreThanOne);
// if (OnlyOne != null) HereYaGo.Add(OnlyOne);
HereYaGo.AddRange(MoreThanOne.Result);
return HereYaGo;
}
}
end Edit
You can try the following with a generic base abstract class
public abstract class Response<T> {
public T Result { get; set; }
}
The concrete implementations would inherit from the common base response.
public class Response : Response<object> {
public object Result { get; set; }
}
public class MultiResponse : Response<List<DeserializedResult>> {
public List<DeserializedResult> Result { get; set; }
}
public class SingleResponse : Response<DeserializedResult> {
public DeserializedResult Result { get; set; }
}

Pass Generic Object To Function And Get Intellisense

I would like to be able to pass a known type to a general function but I'm getting compile errors because I can't cast the type at design time.
Consider my OnCreate function:
EXAMPLE 1:
private void OnCreate<T>(T object)
{
object.CurrentDate = DateTime.Now;
object.SpecialProperty = "Hello";
}
EXAMPLE 2:
private void OnCreate<T>(T object)
{
object.BirthDate = DateTime.Now;
object.BirthdayMessage = "Happy Birthday";
}
I want to call OnCreate and pass to it an object. That object happens to be a model object in an MVC application. I can't predict what model object is being passed to OnCreate yet I want to access the unique properties of the model that is passed. As my examples show above, one model has a CurrentDate and a SpecialProperty property; another has a BirthDate and a BirthdayMessage property. I don't want to create a special function for each because I have many different models. Also, this OnCreate function is going to get inherited from a base class. The idea here is to provide a "hook" into the controller's Create method so that someone can alter the model properties before they are persisted to the database. In other words, the controller's Create method would pass the model to my OnCreate function, then some work would be done on the model before it's passed back.
As you would expect, each model has different properties. Due to this requirement, I realize that I won't be able to early-bind and get intellisense with the OnCreate function--but my problem is that the compiler won't let me refer to properties of the object until it knows the object type. I can't cast it at design-time because I don't know the type until run-time.
EDIT
I think my question wasn't so clear, judging by the answers (for which I'm grateful--they're just not what I'm looking for). Perhaps it's better to show how I want to call OnCreate():
OnCreate(model);
Now, when OnCreate receives object "model", it needs to be able to set properties on that model. I suppose I could use reflection on the model and do something like this (this is pseudocode only--still learning about reflection):
if typeof(model) is CustomerModel then
(CustomerModel(model)).BirthDate = "1/1/1960";
(CustomerModel(model)).BirthdayMessage = "Happy Birthday";
elseif typeof(model) is AnotherModel then
(AnotherModel(model)).CurrentDate = DateTime.Now;
(AnotherModel(model)).SpecialProperty = "Hello";
etc...
But I am trying to avoid having a bunch of if/then statements. I prefer if the call could be "routed" to a function that's specific for the type being passed. That way, the call to OnCreate would send the object to an overload(?) so that no reflection logic is needed...
SECOND EDIT
Upon further reflection (no pun intended), I don't think having a bunch of if/else statements in the OnCreate function is the best approach here. I came up with another idea that might work best and accommodates my expressed wish to "avoid having a bunch of if/then statements" (specified in my first Edit): The idea is to have my models implement IOnCreate, which would provide the .OnCreate() method. Thus, my "generic" model objects that implement IOnCreate could be used this way:
model.OnCreate();
Then the OnCreate function would know what properties are on the model:
public void OnCreate()
{
this.BirthdayMessage = "Happy Birthday";
etc...
}
I just see two issues here:
1 - In the controller I would need to test that the model implements IOnCreate--if it doesn't, I wouldn't try to call OnCreate().
2 - I need to be sure that adding a public function such as OnCreate() will not interfere with how EF6 generates database tables in a code-first project.
My question now is whether this approach be best... or whether there is any other idea to consider...
Since T is any type, compiler can't expect it having CurrentDate or SpecialProperty;
you could try solving the problem like that:
public interface IMyInterface {
DateTime CurrentDate {get; set}
String SpecialProperty {get; set}
}
public class MyClassA: IMyInterface {...}
public class MyClassB: IMyInterface {...}
public class MyClassC: IMyInterface {...}
...
private void OnCreate<T>(T value)
where T: IMyInterface // <- T should implement IMyInterface
{
value.CurrentDate = DateTime.Now;
value.SpecialProperty = "Hello";
}
By your example it seems unlikely the Generics are the the solution for you problem (your app), it would seems that a use of an abstract layer (Interface or Abstract Class) is more appropriate.
When using "bare bone" generics any Type can be passed to your method, now since any type in .Net is of type Object you can execute any object related functionality on those generics parameters. To extend this ability of the generics to implements the most basic type in the inheritance hierarchy we have Generics Constraints, those allow you to limit the range of types that can be passed as a generic argument. In your case you'd want to use Type Constraints, which limit the range of types to only those which implement the type specified.
For example, we have type A, and the A has types B and C as derived classes, we want method M to accept only type how implements A:
class Program
{
static void Main(string[] args)
{
M(new A()); // will work
M(new B()); // will work
M(new C()); // will work
M(new D()); // wont work
}
public static string M<T>(T arg)
where T : A
{
return arg.Data;
}
}
public class A { public string Data { get; set; } }
public class B : A { }
public class C : B { }
public class D { }
Edit
According to your last edit it would seems that you have two options to solve this problem.
Implementing an abstraction layer (an Interface): You may want to add an interface and implement it by your models.
public static void OnCreate(IBirthable arg)
{
arg.BirthDate = ...;
}
Interface:
public interface IBirthable
{
DateTime BirthDate { get; set; }
string BirthdayMessage { get; set; }
}
Models:
public class CustomerModel : IBirthable
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
public class AnotherModel : IBirthable
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
Using reflection: If you choose not to use an interface, perhaps is has no logical connection with your models you may want use reflection.
public static void OnCreate<T>(T arg)
{
var type = arg.GetType();
var birthDateProperty = type.GetProperty("BirthDate");
if (birthDateProperty == null)
throw new ArgumentException("Argument not is implementing the model");
birthDateProperty.SetValue(arg, DateTime.Now);
//And so on...
}
Models:
public class CustomerModel
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
public class AnotherModel
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}

Extending using C# generics?

I want to create an extendable nested structure and it seems like I should be able to do this using generics, though I may not be using them "properly".
I want to be able to create child classes from GroupType and/or OptionType. The problem is that I can't perform the new operation on the generic types even though I specified they could only be of a certain base type.
Is there any way to do what I'm trying to do?
public class AllInfo<GroupType, OptionType>
where GroupType: GroupBase<OptionType>
where OptionType: OptionBase
{
public List<string> Names { set; get; }
public List<GroupType> Groups { set; get; }
public AllInfo()
{
DataSet ds = DatabaseRetreival();
this.Groups.add(new GroupType(ds["Name"], ds["Type"]));
}
}
public class GroupBase<OptionType>
where OptionType: OptionBase
{
public string Name { set; get; }
public string Type { set; get; }
public List<OptionType> Options { set; get; }
public GroupBase(string name, string type)
{
this.Name = name;
this.Type = type;
DataSet ds = DatabaseRetreival(this.Type);
this.Options.Add(new OptionType(ds["Name"]));
}
}
public class OptionBase
{
public string Name { set; get; }
public OptionBase(string name)
{
this.Name = name;
}
}
You have to specify the classes must have a default constructor.
where GroupType: GroupBase<OptionType>, new()
View this article and jump down to the section titled Generic Constraints.
You can't specify which constructors a generic class should have. The constructors are not inherited, so even if the base class that you specified has that constructor, a class that derives from it doesn't have to have that constructor.
The only constructor that you can require is the parameterless constructor:
where GroupType: GroupBase<OptionType>, new()
As that only let's you use the parameterless constructor, you would also use a virtual method for putting the data in the object, for example:
GroupType group = new GroupType();
group.Init(ds["Name"], ds["Type"]);
this.Groups.add(group);
The compiler cannot allow that, because it cannot guarantee that the OptionType has a constructor with the right signature. But you can pass a factory function instead of invoking the constructor directly:
public class Foo<T>
{
private List<T> myObjects;
public Foo(Func<string, T> factory))
{
myObjects = new List<T>();
foreach (string s in GetDataStrings())
myObjects.Add(factory(s));
}
}
So if you have a Bar class with a constructor taking a string, you do this:
Func<string,Bar> barFactory = x => new Bar(x);
var foo = new Foo<Bar>(barFactory);
The problem you have is foundationally based in very high amounts of class coupling that you are trying to mitigate with inheritance/generics. I suggest you re-examine why you feel this is necessary. This quest will eventually lead you to interfaces, service-based programming, and IoCs like Ninject or Castle Windsor.
However, if you want a quick fix that further increases code complexity (because you don't have non-complex options here aside from changing your coding philosophy), use an abstract/virtual method, maybe call it Bind(), instead of constructors.
[bolded for tl;dr]

Categories