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
}
Related
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
Can I create an object in place? What I mean is when I have the following class which takes two parameters
class Foo {
public Foo(int x, int y) {}
}
and the following method which takes a Foo object
public void do(Foo foo) {}
can I then write something like this
do({1,2});
instead of this
do(new Foo(1,2));
This would be especially helpful if Foo had a really long name and was surrounded by several namespaces.
No that is not possible.
However if the problem is long names you could try a using alias directive.
using F = A.Very.Long.Namespace.and.classname.FooBarThing;
// ...
List<Bar> list;
// ...
list.Add(new F(1,2));
see https://msdn.microsoft.com/en-us/library/aa664765(v=vs.71).aspx
Short answer
No you cannot. There's only a construct for property/field initialization, e.g.:
new Foo() { a = 2, b = 3 }.
Longer answer
It could beg the question "why not"? Well, I would consider this scenario:
public class Bar : Foo
{
public Bar(int a, int b) : Foo(a, b) {}
}
// ...
List<Bar> list;
// ...
list.Add({1,2});
Now, you at some point you decide that it's a bit strange to have a 'Bar' there in the list, so you change the signature of the list to List<Foo> list;. Your code will now break, because the other constructor is now the 'default'.
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.
I have this factory class which converts a Foo into a list of Bar objects. Foo is a very complex object which I flatten into a list of simple Bar objects. There are about 60 different bits of data that could be transformed from a Foo into a Bar. The following implementation works but there's definite scope for improvement here.
public class FooToBarsConverter
{
public List<Bar> Convert(Foo foo)
{
return Enum.GetValues(typeof(BarTypeEnum))
.Cast<BarTypeEnum>()
.Select(barType => CreateBar(foo, barType))
.Where(newBar => newBar != null)
.ToList();
}
public Bar CreateBar(Foo foo, BarTypeEnum barType)
{
switch (barType)
{
case BarTypeEnum.TypeA:
return CreateTypeA(foo);
case BarTypeEnum.TypeB:
return CreateTypeB(foo);
}
return null;
}
private Bar CreateTypeA(Foo foo)
{
return new Bar(...);
}
private Bar CreateTypeB(Foo foo)
{
return new Bar(...);
}
}
Ideally I'd like to avoid having to write a new case to the switch every time a new BarType is added. Perhaps a dictionary of types and delegate functions but that would still require a mapping of sorts? Is there any feature of the language that I can exploit to avoid this switch case a make the compiler choose the create create function?
Assuming you don't mind the factory methods being statics this does neaten it up a bit without needing the cruft of having to create ~60 more sub-classes to get the type system to do the work for me. I think the statics aren't needed if you make it a func with the factory as well but I've not got that far yet. The statics don't particularly bother me with it just being data transposition
private static readonly IDictionary<BarTypeEnum, Func<Foo, Bar>>
CreateLookup = new Dictionary<BarTypeEnum, Func<Foo, Bar>>
{
{ BarTypeEnum.TypeA, CreateTypeA },
{ BarTypeEnum.TypeB, CreateTypeB }
};
public Bar Create(Foo foo, BarTypeEnum barType)
{
Func<Foo, Bar> createDelegate;
CreateLookup.TryGetValue(barType, out createDelegate);
return createDelegate != null ? createDelegate(foo) : null;
}
private static Bar CreateTypeA(Foo foo) { ... }
private static Bar CreateTypeB(Foo foo) { ... }
Is there any feature of the language that I can exploit to avoid this switch case a make the compiler choose the create create function?
Yes. It's called polymorphism
Check this video: Jimmy Bogard - Crafting Wicked Domain Models on how an enum could be converted into a polimorhic class hierachy.
Basically you create an abstract class called BarTypeEnum that feels like an enum and create n derived types, one for each enum value. Then you could have this method
public abstract Bar CreateBar(Foo foo);
and override it in every subclass each returning a diferent subtype of Bar
e.g.
public override Bar CreateBar(Foo foo)
{
return CreateTypeA(foo);
}
BTW: The enumeration class he talks about is on NuGet as the NuGet package Enumeration
EDIT
I just checked and the nuget package class is not the same as the video. It is a Generic, nonpolimorphic way to implement it though
Not a huge fan of this because it's a bit hard to read, but you can define a custom attribute, mapping each enum value to its method. You'd use reflection to find and execute the appropriate method.
public class BarChooserAttribute : Attribute
{
public BarChooserAttribute(BarTypeEnum barType) { BarType = barType; }
public BarTypeEnum BarType { get; set; }
}
public static class CreateBarMethods
{
[BarChooser(BarTypeEnum.TypeA)]
public static Bar CreateTypeA(Foo foo)
{
return new Bar { Message = "A" };
}
[BarChooser(BarTypeEnum.TypeB)]
public static Bar CreateTypeB(Foo foo)
{
return new Bar { Message = "B" };
}
}
public static Bar CreateBar(Foo foo, BarTypeEnum barType)
{
var methodWrapper = typeof(CreateBarMethods).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Select(m => new { Method = m, Att = (BarChooserAttribute)m.GetCustomAttributes(typeof(BarChooserAttribute), false).Single() })
.Single(x => x.Att.BarType == barType);
return (Bar)methodWrapper.Method.Invoke(null, new[] { foo });
}
To improve performance, you can map the methods into a dictionary one time and retrieve them from the dictionary each time. Additionally, you can use expression trees to compile the methods into lambda expressions, so you only have to do reflection once instead of each time you make the call. Significant performance improvements, to get significantly harder-to-read code, so it's a trade-off.
Personally I don't mind a switch in a factory method, it's readable, it's neat and doesn't sarcrafice the end goal of what a factory method is for - keeping the initialization code together.
However, that being said, I wonder if a custom attribute could tidy this up a bit for you. Going on the assumption all the CreateBarX methods create an instance of Bar initializing the specific properties from Foo.
[System.AttributeUsage(System.AttributeTargets.Field)]
public class FooConverter : System.Attribute
{
public string Parameters;
public Bar GetInstance(Foo foo)
{
var propNames = String.IsNullOrEmpty(Parameters) ? new string[] { } : Parameters.Split(',').Select(x => x.Trim());
var parameters = foo.GetType().GetProperties().Where(x => propNames.Contains(x.Name)).Select(x => x.GetValue(foo));
return (Bar)Activator.CreateInstance(typeof(Bar), parameters.ToArray());
}
}
// extension helpers
public static class EnumExt
{
public static Bar GetInstance(this BarTypeEnum value, Foo foo)
{
var converterAttr = value.GetAttribute<FooConverter>();
return converterAttr != null ? converterAttr.GetInstance(foo) : null;
}
public static T GetAttribute<T>(this System.Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
var attributes = fi.GetCustomAttributes(typeof(T), false);
return attributes.Length > 0 ? (T)attributes[0] : default(T);
}
}
Which would allow you to do
public enum BarTypeEnum
{
[FooConverter] // no properties mapped
TypeA,
[FooConverter(Parameters="Prop1")] // map Prop1 from Foo to Bar
TypeB,
TypeC, // no instance
[FooConverter(Parameters="Prop1, Prop2")] // map Prop1/2 from Foo to Bar
TypeD,
TypeE // no instance
}
public List<Bar> Convert(Foo foo)
{
return Enum.GetValues(typeof(BarTypeEnum))
.Cast<BarTypeEnum>()
.Select(barType => barType.GetInstance(foo))
.Where(newBar => newBar != null)
.ToList();
}
And that's all you need!
However, there are some limitations to this approach with respect to the parameter injection, CreateInstance will only match the constructor based on a signature which matches the data type i.e.
// this will call Bar(string prop1, string prop2)
Activator.CreateInstance(typeof(Bar), new object[] { "Property1", "Property2" });
// where as this will car Bar(string prop1)
Activator.CreateInstance(typeof(Bar), new object[] { "Property2" });
The ordering is important as well
// this will call Bar(string prop1, string prop2) so Prop1 = "Property2"
Activator.CreateInstance(typeof(Bar), new object[] { "Property2", "Property1" });
However, there are ways around this - for the most part this will probably work well.
I hate 'case's and I like Generics therefore I slightly changed interface of FooToBarsConverter:
public interface IFooToBarsConverter
{
List<Bar> Convert(Foo foo);
Bar CreateBar<TBarType>(Foo foo) where TBarType : Bar;
}
There is an implementation:
public class FooToBarsConverter : IFooToBarsConverter
{
public List<Bar> Convert(Foo foo)
{
return new List<Type>
{
typeof(Bar.BarA),
typeof(Bar.BarB)
}.Select(it => CreateBar(foo, it))
.ToList();
}
public Bar CreateBar<T>(Foo foo)
where T : Bar
{
return CreateBar(foo, typeof(T));
}
private Bar CreateBar(Foo foo, Type barType)
{
return typeof(Bar).IsAssignableFrom(barType)
? (Bar)Activator.CreateInstance(barType, foo)
: null;
}
}
public class Foo
{
}
public abstract class Bar
{
private Bar(Foo foo)
{
}
public class BarA : Bar
{
public BarA(Foo foo)
: base(foo)
{
}
}
public class BarB : Bar
{
public BarB(Foo foo)
: base(foo)
{
}
}
}
... and a test that tests it:
[TestMethod]
public void TestMethod()
{
// arrange
var foo = new Foo();
var target = new FooToBarsConverter();
// act + assert
var list = target.Convert(foo);
list.Should().HaveCount(2);
list.Should().NotContainNulls();
var typeA = target.CreateBar<Bar.BarA>(foo);
typeA.Should().BeAssignableTo<Bar.BarA>();
var typeB = target.CreateBar<Bar.BarB>(foo);
typeB.Should().BeAssignableTo<Bar.BarB>();
}
This is what I need to do:
object foo = GetFoo();
Type t = typeof(BarType);
(foo as t).FunctionThatExistsInBarType();
Can something like this be done?
You can use the Convert.ChangeType method.
object foo = GetFoo();
Type t = typeof(string);
string bar = (string)Convert.ChangeType(foo, t);
No, you cannot. C# does not implement duck typing.
You must implement an interface and cast to it.
(However there are attempts to do it. Look at Duck Typing Project for an example.)
Since dynamics were added to c#, I think we can do it in this way:
class Program {
static void Main(string[] args) {
List<int> c = new List<int>();
double i = 10.0;
Type intType = typeof(int);
c.Add(CastHelper.Cast(i, intType)); // works, no exception!
}
}
class CastHelper {
public static dynamic Cast(object src, Type t) {
var castMethod = typeof(CastHelper).GetMethod("CastGeneric").MakeGenericMethod(t);
return castMethod.Invoke(null, new[] { src });
}
public static T CastGeneric<T>(object src) {
return (T)Convert.ChangeType(src, typeof(T));
}
}
Your original question was flawed in that you ask to treat a variable as a type which is not known at compile time but note that you have string defined on the left hand side when you declare your variable. C# as of 3.5 is statically typed.
Once dynamic is available you could do something like this:
dynamic foo = GetFoo();
foo.FunctionThatExistsInBarType();
For when you don't know what the type is but you know it will always support the instance method FunctionThatExistsInBarType();
for now you are forced to use reflection (or code gen which really amounts to much the same thing but more expensive up front and faster later).
// any of these can be determined at runtime
Type t = typeof(Bar);
string methodToCall = "FunctionThatExistsInBarType";
Type[] argumentTypes = new Type[0];
object[] arguments = new object[0];
object foo;
// invoke the method -
// example ignores overloading and exception handling for brevity
// assumption: return type is void or you don't care about it
t.GetMethod(methodToCall, BindingFalgs.Public | BindingFlags.Instance)
.Invoke(foo, arguments);
Provided you know all required types at compile-time, duck typingis (sort of) possible:
class BarFoo {}
class Foo {}
class Bar {}
class Program
{
static void Main( )
{
var foo = new Foo( );
var bar = new Bar( );
var barfoo = new BarFoo( );
Console.WriteLine(DoStuff(foo));
Console.WriteLine(DoStuff(bar));
Console.WriteLine(DoStuff(barfoo));
}
static string DoStuff(Foo foo) { return "DoStuff(Foo foo)"; }
static string DoStuff(Bar bar) { return "DoStuff(Bar bar)"; }
static string DoStuff(Base fb) { return "DoStuff(object fb)"; }
}
Output:
Dostuff(Foo foo)
Dostuff(Bar bar);
DoStuff(object fb);
If you end up implementing a lot of methods that basically do exactly the same, consider implementing an interface.