Anonymous type as method parameter - c#

My first try to use anonymous types(test):
private void button4_Click(object sender, EventArgs e)
{
test(new { a = "asd" });
}
private void test(string a)
{
}
I get an error "cannot convert from 'AnonymousType#1' to 'string' "
Also I'd like to know how to pass an anonymous type if the parameter is a string[]
private void test(string[] a)
{
}
Thanks in advance!

Something about your design is faulty. If your test function accepts only strings, then you can never pass an anonymous type to it, just as you can't pass an int, object, or any other non-string type.

a is a string property on your anonymous type
private void button4_Click(object sender, EventArgs e)
{
test((new { a = "asd" }).a);
}
private void test(string a)
{
}
Edit: Anonymous types do not derive from anything other than object so you cannot create a method that expects an anonymous type parameter.
Edit 2: when you create an anonymous type the compiler create an entirely new type based on the properties you set and the order in which they appear. You cannot create an anonymous type and use it in place of any other type (other than object). The most common scenario I've used them in is for binding when you need to flatten your object graph.
warning, I am horrible at coming up with good example scenarios and this is all from memory!
for example if I had a list of Person objects that had a name property and an address property that contained the street address and needed to bind to a list box
var people = new List<Person>()
listbox.TextMember = "Text";
listbox.ValueMember = "Value"
listbox.DataSource = from p in people
select new { Text = p.Name, Value = p.Address.StreetAddress };

There is no clean way to pass an anonymous type between methods; you're not meant to do it. Create a real type instead.
If you really really want to do this, you can use a helper method to fake it awkwardly by creating another "template" of that type to cast to later; see this and many similar articles.
EDIT: On closer examination, you don't appear to understand what an anonymous type actually is, so I suggest you take the other answers.

Just stumbled upon this outdated question and thought somebody here should mention possibility to use dynamic starting with C# 4.0 which is perfect for working with anonymous types. I.e. the code could be looking like this:
private void button4_Click(object sender, EventArgs e)
{
test(new { a = "asd" });
}
private void test(dynamic obj)
{
Console.WriteLine(obj.a);
}

This is bad, but it works ...
namespace AnonType
{
class Program
{
static void Main(string[] args)
{
var foo = new { a = "123", b = "abc" };
Anon(foo);
Console.ReadLine();
}
public static void Anon(object o)
{
Console.WriteLine(o);
}
}
}

Related

Call a generic method with a specific type only known at run time and return that type?

I am trying to set up a networked event system in my Unity Project that allows triggering events on other clients. The event also is supposed to pass an EventArgs-type specific to that event.
However, apparently System.EventArgs is not Serializable and thus can not be directly sent over the MLAPI Network. Therefore I convert the class to a string with Unity's JsonUtility class and instead send that string. Additionally, I send another string which is the specific eventArgsType.ToString().
On client side, I am then converting the eventArgsType to a Type with GetType, and would then like to Deserialize the data-string into the correct eventArgs class. Which I currently do by nasty if-else case comparing to the possible eventArgs-Subtypes and then Deserialize as that. That works, but is extremely ugly and will get out of hand the more subtypes I have. But I am not quite sure of how to do that and would appreciate any tips.
What I currently have:
public class EventSystem : NetworkBehaviour
{
[...]
public void TriggerLocalAndNetwork(string eventName, EventArgs data)
{
ulong clientId = NetworkManager.Singleton.LocalClientId;
if (Instance._eventDictionary.TryGetValue(eventName, out var triggeredEvent))
{
triggeredEvent.Invoke(clientId, data); // Local Trigger
string argsTyp = data.ToString();
EventToServerRpc(eventName, clientId, EventArgsSerializer.Serialize(data), argsTyp);
}
}
[ServerRpc(RequireOwnership = false)]
private void EventToServerRpc(string eventName, ulong clientId, string data, string argsType)
{
EventToClientRpc(eventName, clientId, data, argsType);
}
[ClientRpc]
private void EventToClientRpc(string eventName, ulong clientId, string data, string argsType)
{
if (clientId == NetworkManager.Singleton.LocalClientId)
return;
if (!Instance._eventDictionary.TryGetValue(eventName, out var triggeredEvent))
return;
Type args = Type.GetType(argsType);
EventArgs eventArgs = EventArgs.Empty;
// This is what I want to get rid off
if (args == typeof(MagicAttackEventArgs))
{
eventArgs = EventArgsSerializer.Deserialize<MagicAttackEventArgs>(data);
}
else if (args == typeof(HealthSystem.HealthSystem.TakeDamageEventArgs))
{
eventArgs = EventArgsSerializer.Deserialize<HealthSystem.HealthSystem.TakeDamageEventArgs>(data);
}
triggeredEvent.Invoke(clientId, eventArgs);
}
}
public static class EventArgsSerializer
{
public static string Serialize(EventArgs eventArgs)
{
string json = JsonUtility.ToJson(eventArgs);
return json;
}
public static T Deserialize<T>(string input)
{
T eventArgs = JsonUtility.FromJson<T>(input);
return eventArgs;
}
}
What I tried instead of the if-else part is this:
Type args = Type.GetType(argsType);
MethodInfo method = typeof(EventArgsSerializer).GetMethod(nameof(EventArgsSerializer.Deserialize));
MethodInfo generic = method.MakeGenericMethod(args);
var result = generic.Invoke(null, new object[]{data});
EventArgs eventArgs = (EventArgs) Convert.ChangeType(result, typeof(EventArgs));
triggeredEvent.Invoke(clientId, eventArgs);
But it yield a casting error, and I am not sure if I used the tools correctly at all, it was inspired just inspired by https://stackoverflow.com/a/232621 this answer.
As per the docs there is an overload of that FromJson method which takes a Type
Type args = Type.GetType(argsType);
EventArgs eventArgs = (EventArgs)JsonUtility.FromJson(data,args);
I would suggest using a serialization library with support for polymorphism. See for example the article for System.Text.Json, but this is a rather common feature for most serialization libraries.
This lets you use a common base class for messages that can be used when de-serializing. I would recommend defining your own message-type, rather than just using EventArgs.
There are a few different ways to do different things depending on the message:
A virtual method, probably the simplest option, but may be more difficult to use if the method needs different parameters depending on the actual type.
pattern matching
The visitor pattern

Casting object to type into variable of said type known only at runtime

Can someone help me to understand why the below doesn't work?
void test(int i)
{
Console.WriteLine("int");
}
void test(String s)
{
Console.WriteLine("String");
}
void runMe()
{
object obj = 1;
Type t = typeof(int);
test((t)obj);
}
You get a "The type or namespace name 't' could not be found" error.
Is there a way to make this work? I need to cast an object to a specific type known only at runtime, but all options I've found are simply converting the data but still storing them in an object.
Edit: Added some pseudo methods to give more context.
It looks like you're basically trying to perform dynamic dispatch. The way you're trying it won't work, because while you work with static typing, all overload resolution is performed at execution.
However, you can use dynamic typing for this instead, with the dynamic type. At that point, overload resolution is performed at execution time instead:
void Test(int i)
{
Console.WriteLine("int");
}
void Test(String s)
{
Console.WriteLine("String");
}
void RunMe()
{
dynamic obj = 1;
// The right overload is picked at execution time
Test(obj);
}
That will accomplish what you've shown in your question - but it's not necessarily the best approach. If you can possibly stick to static typing (without using reflection) I would do so. If you can only handle a known set of types, you might want to keep a Dictionary<Type, Action<object>> or something like that... although you then need to consider awkward things like subtyping etc.
If you do use dynamic typing, I'd try to use it for just a small piece of your code. As soon as you can get back "out" of dynamic typing, do so (e.g. by casting the result of a dynamically-bound call to its expected return type).
Here's an example with a few ways to do it combined into one example.
First method is to overload your method for supported types (these can get called directly when type is known at compile-time) and create a catch-all default overloaded method with parameter of type object which internally checks for supported types and calls the appropriate type-specific method (this is for types only known at run-time).
Second method can be used as an extension to the first, but you can also implement just the second method and skip the first part. Since you know the type at the start of the run-time and the type is not expected to change with each call, you can skip the per-call type checking and instead do a check once when you load the config, then set the appropriate delegate.
try it: https://dotnetfiddle.net/06JYE1#
using System;
public class Program
{
public static void Main()
{
var p = new Program();
object s = "Hi";
object i = 42;
object f = 3.14;
p.Test(s);
p.Test(i);
p.Test(f);
p.SetTestType(GetConfigType());
p.ConfiguredTest("Hello");
p.ConfiguredTest(s);
}
public static Type GetConfigType() { return typeof(string); }
Action<object> ConfiguredTest;
void SetTestType(Type type)
{
if (type == typeof(string))
ConfiguredTest = o => Test((string)o);
else if (type == typeof(int))
ConfiguredTest = o => Test((int)o);
else
ConfiguredTest = null;
}
void Test(object o) // catch-all when type is not known until runtime
{
if (ConfiguredTest != null)
{
ConfiguredTest(o); // if type is configured, we can skip type checking
}
else // if type is not configured, check for supported types
{
if (o is string)
Test((string)o);
else if (o is int)
Test((int)o);
else
Console.WriteLine("Unsupported type: " + o.GetType());
}
}
void Test(int i) { Console.WriteLine("Int = " + i); }
void Test(String s) { Console.WriteLine("String = " + s); }
}

C# dynamic field depending on "T" type, without hardcoding

So I have a function. It takes in an object called 'item' of an unknown type. In the function, it declares an object, and depending on what the Type is, depends on what field of 'item' the object gets a value from, for example:
private static void CreateObject<T>(T item)
{
SomeObject object = new SomeObject();
//if 'item' is type "A"
// object.Text = item.Display
//else if 'item' is type "B"
// object.Text = item.Text
//else if 'item' is type "C"
// object.Text = item.Value
}
Please note, passing the string of 'item.display' or which ever is not an option, as alot goes on in this function, and this is a simplified version of the function for explaining whats required.
How could this be done in a more elegant way?
I have looked at reflection but been instructed to avoid this as it is expensive (hardware, memory etc)
Take a delegate parameter that will provide the Text
private static void CreateObject<T>(T item, Func<T, object> prop)
{
SomeObject obj = new SomeObject();
obj.Text = prop(item).ToString();
}
So the caller of the method will use
CreateObject(a, t => t.Display);
CreateObject(b, t => t.Text);
// etc
You could apply the adapter pattern and pass in an adapter object that will return display text and other things. That object can be constructed by the caller as appropriate (presumably, the caller will know more about the nature of the object it is sending in to CreateObject()). Examples:
interface IMyAdapter {
string GetDisplayText();
// ...
}
class TextBoxAdapter : IMyAdapter {
private readonly TextBox tb;
public TextBoxAdapter(TextBox tb) {
this.tb = tb;
}
public string GetDisplayText() {
return tb.Text;
}
// ...
}
...
public static void CreateObject(IAdapter adapter) {
SomeObject obj = new SomeObject();
obj.Text = adapter.GetDisplayText();
// ...
}
...
var textBoxAdapter = new TextBoxAdapter(new TextBox());
CreateObject(textBoxAdapter);
In addition to Eranga's answer about passing a delegate, if you do not want to litter delegates all over your calling code you could create non-generic overloads for this function to do it for you.
private static void CreateObject<T>(T item, Func<T, string> prop) {
SomeObject obj = new SomeObject();
obj.Text = prop(item);
}
private static void CreateObject(TypeA item) {
CreateObject(item, i => i.Display);
}
private static void CreateObject(TypeB item) {
CreateObject(item, i => i.Text);
}
This would centralise the delegates, while still pulling it away from the middle of the body of your function.
I think to give the "best" answer though, we would need to know a lot more about the size and purpose of this method, where it is being called from etc.
There are many ways you could approach this, and honestly under some circumstances there would be nothing wrong with your series of if statements. It is clear, any programmer should understand it and if you only have a couple of cases just do it and get on with solving real problems.

How do i assigned the type of any object to a .NET generic method?

Suppose that I have created a method like this
private void Test<t>(t str)
{
}
Now from another method i call it
private void BtnClick()
{
string a = "";
test<Here I Want To assign The Type what ever the type of 'a' is>();
}
How can I do this ?
Well, if a is a string, you can write:
Test<string>(a);
And if a is an int, you can write:
Test<int>(a);
Pretty obvious. If you don't know the type of a upfront, that means that BtnClick should be generic, the problem would be moved to BtnClick's caller:
private void BtnClick<T>()
{
T a = ...;
Test<T>(a);
}
C# 2.0 and later offers type inference, so you wouldn't have to specify the type:
Test(a);
You simply call the function passing a as the parameter. Type inference will determine what T should be for a.
static void Main()
{
string temp = "blah";
Test(temp);
Console.Read();
}
private static void Test<T>(T input)
{
Console.WriteLine(typeof(T).ToString());
}
System.String would be printed to the console.
Edit: But, yes, absent type inference, and when you know what your type your variable is, you can always be explicit with the type. Test<string>(temp);
In your example, a is always a string, so you can simply use either Test<string>(a) or Test(a). If, however, you mean that you have a Type instance hanging around somewhere, then you get into the area of reflection. Note that this works, but is slow if used in a tight-loop, so make sure that you understand the performance aspect;
object arg = ...;
MethodInfo method = typeof(YourType)
.GetMethod("Test", BindingFlags.NonPublic | BindingFlags.Instance)
.MakeGenericMethod(arg.GetType());
method.Invoke(this, new object[] { arg });

Declaring the type for a templatized function in C#

In c# it's possible to create a list of functions like so:
var myList = new List< Func<Foo> >();
This will allow functions (delegates) that take no arguments and return a value of type Foo to be added to the list. So something like:
Foo myFunc1() { ... }
would be a valid member of that list. My question is, how do I declare the type for a templatized function? How can I construct a List<> that will hold functions of the form:
T myFunc2<T>() { ... }
You need to do that inside a templatized class or method. Then you can refer to the generic type T just as you would refer to the specific type Foo.
In other words:
public class FuncContainer<T>
{
private List<Func<T>> list = new List<Func<T>>();
public void Fill()
{
// Initialize list
}
}
I think the other answers so far have misunderstood the problem... and I don't think you can actually do it, if I've read it correctly. Am I right in saying you'd like to be able to write this:
List<???> list = new List<???>(); // This line won't work
list.Add(Method1);
list.Add(Method2);
...
static int Method1() { ... }
static string Method2() { ... }
If I've misunderstood, and a simple generic type parameter of T in your method or class suffices, I'll delete this answer :)
The closest you could come to the above would be something like this:
public class FuncList
{
private readonly List<Delegate> list = new List<Delegate>();
public void Add<T>(Func<T> func)
{
list.Add(func);
}
}
You'd then use it as:
FuncList list = new FuncList();
list.Add<int>(Method1);
list.Add<string>(Method2);
Quite what you'd do with the list afterwards is tricky... what did you have in mind?
Yes this first signature is completely valid.
The signature of the last function you suggested is the following
List<Func<T>> x;
This holds a list of delegates which take no arguments and produce a T value.

Categories