Convert/Parse many Objects using a member Method with less Code - c#

Is there any simple way to convert/parse many Objects of Class Foo to objects of class Bar, using a member method of class Bar like Bar.loadFromFooObject(Foo classFoo) ?
So if I have those 2 Classes:
class Foo
{
public string var1;
public int var2;
public List<string> var3;
}
class Bar
{
public string var1;
public int var2;
public float var4;
public void loadFromFooObject(Foo fooObj)
{
this.var1 = fooObj.var1;
this.var2 = fooObj.var2;
}
}
So that I can avoid doing:
Foo[] fooObjs = { new Foo(), new Foo(), new Foo()};
Bar[] barObjs = new Bar[fooObjs.Length];
for (int i = 0; i < fooObjs.Length; i++)
{
barObjs[i].loadFromFooObject(fooObjs[i]);
}
And do something like:
Foo[] fooObjs = { new Foo(), new Foo(), new Foo()};
Bar[] barObjs = fooObjs.Parse(loadFromFooObject);
Is something like this possible using C# and/or Linq?

Write a method TransformFooToBar and then use the linq, e.g.,
var barObjs = fooObjs.Select(n => TransformFooToBar(n)).ToArray();
If you really want it to be a method on the Bar class, write an extension method, and then linq looks like this:
var barObjs = fooObjs.Select(n => n.TransformFooToBar()).ToArray();

I use this strategy a lot for any kind of object conversion/mapping:
Create the function for a single object conversion
Create an overload accepting an IEnumerable (usually a List for me) and use LINQ .Select to convert the entire list into. It codes seamlessly since the single object conversion is, by definition, a Func. See this SO answer for more explanation on Funcs.
You can also get fancy with extension methods by creating a few extension methods in a static class. For you case specifically, the extension methods could look like this:
public static class ExtensionMethods
{
public static Bar ToBar(this Foo foo)
{
var bar = new Bar();
bar.loadFromFooObject(foo);
//you could also move the logic to convert from the Bar class in here
return bar;
}
//Overload for a collection of Foos (like Foo[] or List<Foo>)
public static IEnumerable<Bar> ToBars(this IEnumerable<Foo> foos)
{
//Since ToBar is a Func<Foo, Bar>
return foos.Select(ToBar);
//alternate lambda syntax: return foos.Select(foo => foo.ToBar());
}
}
And you would call these methods like this:
var fooList = new List<Foo>();
var barEnumerable = fooList.ToBars();

This something like this, all you need to create a ConvertToBar method which takes a Foo and returns a Bar.
var barObjs = fooObjs.Select(i=>ConvertToBar(i)).ToArray();

My preference (and it is just a personal preference) is to override the explicit cast operator and just cast from one type to the other. Combine that with Kye's answer to handle multiple objects.

Related

c# combine multiple types into one

I'm facing a problem that I need to construct one object from multiple types and return to the front end, here is what I want(In C#).
The shape that front end wants is like this
{
...
"props" : // this is the place I need to fill-up.
...
}
For the controller, it's a custom response.
public IActionResult Index()
{
return JohnDoe.Render();
}
Behind the scenes, Render is going to get some data from two places.
public object Foo()
{
return string, int, IEnumerable, instance, etc;
}
public object Bar()
{
return string, int, IEnumerable, instance, etc;
}
I know the return statement is not valid, what I mean is that those are all the possibilities.
And here is eventually what I want.
public object Combine()
{
var foo = Foo();
var bar = Bar();
return foo + bar;
}
Again the return statement is not valid, I want to have a final object that contains both of them. It can be Dictionary<string, object> or anonymous object new {}, or something else does not matter as long as one object has both of them.
Obviously what I have here is not possible to achieve it. Here are the two options I came up with.
Just use a wrapper to wrap them, Here is what I do.
public object Combine()
{
var foo = Foo();
var bar = Bar();
return new { foo, bar };
}
I know I can have a Type rather than an anonymous object, the thing is that this will introduce two keys foo and bar, which I do not want to if possible.
Make the foo and bar only return instance. NO string, int, Array, IEnumerable etc.
If I do it in this way, things get a little bit easier. All I need to do is looping through the properties getting the values and map to either new {} or Dictionary<string, object>. This way I do not need to introduce new keys.
Update : so basically I want to avoid introducing new keys if I can, as I just want to return the original without a wrapper. That's why I came up with option 2, only instance is allowed. Let me know your thoughts, please.
You can use a Tuple:
public Tuple<Foo, Bar> Combine()
{
var foo = Foo();
var bar = Bar();
return Tuple.Create(foo, bar);
}
Or a ValueTuple:
public (Foo, Bar) Combine()
{
var foo = Foo();
var bar = Bar();
return (foo, bar);
}
Also with named fields:
public (Foo foo, Bar bar) Combine()
{
var foo = Foo();
var bar = Bar();
return (foo, bar);
}
Or, as Dennis1679 suggest, make a custom type.
How about option 3)
create a class that acts as a wrapper for Foo and Bar called FooBar ?
public class FooBar
{
public Foo Foo { get; set; }
public Bar Bar { get; set; }
}
Why?
C# is an object-oriented programming language. And it's based on the concept of wrapping pieces of data, and behavior related to that data, into special bundles, called objects, which you construct from a 'blueprint' called a class.
I think this is what you are asking
public sealed class FooBar : Foo, Bar
{
}
Unfortunately this is not possible in C#. But in essence this is what you are doing. You can do the following:
public sealed class FooBar: IFoo, IBar
{
public FooBar(IFoo foo, IBar bar)
{
///Assign its members
}
///Implement its members
}

deriving types from an array of individually typed classes

I'm trying to come up with the best way to pass multiple individually typed classes into a method. I won't know beforehand how many individually typed classes will be passed into the method so have started the code off like this...
An Interface
public interface ITypedClass {}
A Typed Class
public class TypedClass<T> : ITypedClass
{
public IEnumerable<T> Output() {}
}
A Method
public static void DoSomething(params ITypedClass[] typedClasses) {}
... and with these run something like the following, where the DoSomething method populates the typed classes with respective values based on the collective of what is passed into the DoSomething method.
var typedClassA = new TypedClass<TypeA>();
var typedClassB = new TypedClass<TypeB>();
...
var typedClassN = new TypedClass<TypeN>();
DoSomething(typedClassA, typedClassB, ... typedClassN etc
var valueA - typedClassA.Output();
var valueB - typedClassB.Output();
...
var valueN - typedClassN.Output();
Unfortunately inside the DoSomething method...
var typedClass = (TypedClass<T>)typedClasses.First();
... the individual values in the typedClasses parameter can't be converted back to TypedClass because the DoSomething method doesn't know what T is in each instance.
Can anyone think of a better way to do this?
The answer seems a little bit obvious with more thought. Had to sleep on it a few nights before the obviousness finally clicked. Don't have DoSomething process the typed input, have TypedClass do it for you and instead have DoSomething split up the work.
New Interface
public interface ITypedClass
{
void Input(object value);
}
New Typed Class
The Input method here handles the conversion from object value to List value
public class TypedClass<T> : ITypedClass
{
public List<T> value;
public void Input(object value) {...}
public IEnumerable<T> Output() => value;
}
New Method
DoSomething now divides up the work...
public static void DoSomething(params ITypedClass[] typedClasses)
{
foreach (var c in typedClasses)
{
c.Input(...);
}
}
Now when calling the following ...
var typedClassN = new TypedClass<TypeN>();
DoSomething(... typedClassN ... );
var valueN = typedClassN.Output();
valueN will have a value and DoSomething can handle a variable amount of typed classes

How can I add an extension method to many classes?

I have about 1000 classes in which i need to count the number of properties of. I have the following code:
public static int NumberOfProperties()
{
Type type = typeof(C507);
return type.GetProperties().Count();
}
I could copy and paste this in to each class changing the typeof parameter but this seems a bit tedious.
Is there anyway to make an extensions method to do this by just doing var nop = C507.NumberOfProperties();?
Just to add to the answers suggesting an extension for object for completeness: you can also consider implementing an extension only for Type:
public static int GetPropertyCount(this Type t)
{
return t.GetProperties().Length;
}
and use it like this:
typeof(C507).GetPropertyCount();
The advantage is that you can get the number of properties directly from the type and do not have to create an instance first.
So you can write an extension method that uses object or one that uses type.
public static class ObjectExtensions
{
public static int GetNumberOfProperties(this object value)
{
return value.GetType().GetProperties().Count();
}
public static int GetNumberOfProperties(this Type value)
{
return value.GetProperties().Count();
}
}
Usage:
new C507().GetNumberOfProperties();
typeof(C507).GetNumberOfProperties();
However, you explicitly state two things:
I could copy and paste this in to each class changing the typeof
I have about 1000 classes
You'll likely not want to instantiate a 1000 classes or copy and paste typeof() 1000 times
In this case, you will want to read them all from the Assembly.
So something like:
typeof(SomeClass).Assembly.GetTypes().Select(x => new
{
x.Name,
PropertyCount = x.GetType().GetProperties().Count()
});
Where SomeClass is a class (doesn't matter which) where all the classes reside.
I just simply select them out into an anonymous object which contains the Types name and property count.
This:
typeof(SomeClass).Assembly
Is just a convience way to get the assembly. There are other ways.
Assembly.GetAssembly(typeof(Program)).GetTypes()
Assembly.GetCallingAssembly().GetTypes()
Assembly.Load("Some Assemble Ref").GetTypes()
You can do allsorts with the types that you find. If you select out the Type itself, you can instantiate it later using Activator.CreateInstance (if it has parameterless constuctor). You can also auto fill the properties with reflection as well.
It is impossible to have a static extension method as you imagine it. That being said, it would be possible to create a generic method in a helper class as follows.
public static int NumberOfProperties<T>()
{
Type type = typeof(T);
return type.GetProperties().Count();
}
Given a type SomeType it could be called as int n = NumberOfProperties<SomeType>().
You could make an extension method on object like this:
public static int PropertyCount(this object thing)
{
return thing.GetType().GetProperties().Count();
}
And use it on any object you like:
var x = "some string";
var numProps = x.PropertyCount();
If you want to have an extension method on object:
public static ObjectExtensions
{
public static int NumberOfProperties(this object value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetType().GetProperties().Length;
}
}
...
C507 myObj = new C507();
// How many properties does myObj instance have?
int propCount = myObj.NumberOfProperties();
If you want to have an extesnion method on Type:
public static TypeExtensions
{
public static int NumberOfProperties(this Type value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetProperties().Length;
}
}
...
// How many properties does C507 type have?
int propCount = typeof(C507).NumberOfProperties();
There are a couple of ways to do this that are variations of the same thing.
You can pass the Type as an argument to a method:
public static class Helper {
public static int NumberOfProperties(Type type)
{
return type.GetProperties().Count();
}
}
Which you would call like this:
// Imagine you have a class called MyClass
var result = Helper.NumberOfProperties(typeof(MyClass));
You use use the generic system in C# to make the syntax a little cleaner. That would look like this:
public static class Helper {
// Notice the argument was removed and
// the use of the "generic" syntax <T>
public static int NumberOfProperties<T>()
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
And you would call it like this:
var result = Helper.NumberOfProperties<MyClass>();
You could also use "Extensions" which allow you to call it as if it was a method that belonged to your classes.
public static class Helper {
// notice the `this` keyword before the parameter
// this is what tells C# that this is an extension method
public static int NumberOfProperties<T>(this T #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
This will allow you to call the method like this:
var instance = new MyClass();
var result = instance.NumberOfProperties();
In this example I used the generic syntax so that it applies to any type of object. If you wanted to limit it to only objects that inherit from a specific interface or base class you would just change it from using the generic syntax to using the base class/interface. Like this:
public static class Helper {
// notice the type got changed from a generic <T>
// to specifying the exact class you want to "extend"
public static int NumberOfProperties(this MyBaseClass #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
As #rené-vogt mentioned you can also create the extension method so that it extends the type Type instead. See his answer in this thread: https://stackoverflow.com/a/38455233/984780
You can make a generic extension method which can apply to all types:
public static int PropertyCount<T>(this T obj)
{
return typeof(T).GetProperties().Length;
}
This will apply to all types including value types (I.E. structs) which applying to object will not. Thanks to piedar for pointing out my mistake here, applying to object does still add this extension method to value types.
If your classed can implement an interface, then you can extend that interface.
public interface IExtensible {
}
class C507 : IExtensible {
}
public static int NumberOfProperties(this IExtensible extensible)
{
Type type = extensible.GetType();
return type.GetProperties().Count();
}
That being said, having hundreds of (generated?) classes looks like a bad solution to begin with.

Inheritance of a List in C#, and explicit casting after a FindAll()

I have a class that subclass a generic List.
I did it to implement a toJSONString() that I need to call regularly on this kind of list.
So my class is something like this:
public class Foos : List<Foo>
{
public string toJSONString()
{
//Do something here
}
}
In another Class i have a method doing this:
public class Bar
{
private Foos m_Foos = new m_Foos();
public Foos filterWith(Query p_query)
{
Foos newList = m_Foos.FindAll(
// Make a test through a delegate
});
return (newList);
}
}
I get this error:
Error CS0266: Cannot implicitly convert type System.Collections.Generic.List<Foo>' toFoos'. An explicit conversion exists (are you missing a cast?) (CS0266) (Assembly-CSharp)
The problem is that m_Foos.FindAll(...) return a "List" not a "Foos".
Explicit casting doesn't do the trick, because I then have a runtime error.
I have read this post, but it doesn't seem to give an appropriate solution to my problem:
C# - Why can I not cast a List<MyObject> to a class that inherits from List<MyObject>?
Do not write a new class just to add such formatting method. Use extension method instead on your list:
public static class FooListExtensions
{
public static string toJSONString(this List<Foo> list)
{
return "...";
}
}
Then you can simply:
List<Foo> list = new List<Foo>();
var str = list.toJSONString();
m_Foos.FindAll(
// Make a test through a delegate
});
This method returns List<Foo>. You cannot cast List<Foo> to Foos, (only Foos -> List<Foo> - due to inheritance).
You could prepare sufficient constructor:
public class Foos : List<Foo>
{
public Foos()
{
}
public Foos(List<Foo> otherList)
: base(otherList)
{
}
public string toJSONString()
{
//Do something here
}
}
Then:
Foos newList = new Foos(m_Foos.FindAll(/* delegate */));
This has to do with Liskov Substitution Principle. Let's say you have classes Rectangle and Square and that square inherits from a rectangle. You can cast square to a rectangle - square is a rectangle with 4 same sides, but you cannot cast rectangle into a square since rectangle is not a square. In other words you can cast up the inheritance tree but not down the inheritance tree.
I would follow Konrad's suggestion and make it into an extension method if the only reason why you created a Foos class is so that you can convert it to a JSON...

Comparing for sorting in different ways

I have a class that implements IComparable. It works but the comparison is static, i.e. it's always the same ordering it achieves. What would be a good method to introduce comparison by a parameter, i.e. if we have:
class Poo : IComparable {
public int A { ... };
public int B { ... };
...
}
IEnumerable<Foo> list = ...;
list = list.Sort(???);
I' d like to order the list with respect to A or B depending on the parameter passed to Sort at the question marks. What's the most efficient way to do that?
At the moment, the best method I've came up with is to declare a couple of methods that I pass to Sort as delegates.
private static int CompareWrtA(Foo foo1, Foo foo2) { ... }
private static int CompareWrtB(Foo foo1, Foo foo2) { ... }
if(withRespectToA)
list = list.Sort(CompareWrtA);
else
list = list.Sort(CompareWrtB);
But it doesn't feel really as the best way. Criticism is welcome.
If you want to simplify that statement you can write it like this:
list.Sort((x,y) => withRespectToA ? CompareWrtA(x,y) : CompareWrtB(x,y));
BTW, Sort method is modifying your list, it doesn't return anything.So you don't need to assign it back to your list.

Categories

Resources