Is there any way to pass an undefined object as parameter? c# - c#

I have a method that works with a defined data object type, like this:
public static ItemEdificio JSONtoOBJECT(this string JSONstring)
{
return new JavaScriptSerializer().Deserialize<ItemEdificio>(JSONstring);
}
Is there any way to convert the "ItemEdificio" into something than actualy vary according to the object type?
Keep in mind that this is made using the Newtonsoft library.

public static T JSONtoOBJECT<T>(this string JSONstring)
{
return new JavaScriptSerializer().Deserialize<T>(JSONstring);
}
Thats what generics (https://msdn.microsoft.com/en-us/library/0x6a29h6.aspx) are for.
You call it like this: MyType instance = jsonData.JSONtoOBJECT<MyType>();

Related

Pass js object to C# function

I'm trying out Jint and want to implement the fetch api to use from js. The second argument is a nested js object that is passed in:
fetch('https://example.com', {
method: 'post',
headers : {
authorization : 'xyz'
}
});
What is the signature for the C# function to pass in? I tried
private static string Fetch(string uri, object init)
First and saw Jint passed in an ExpandoObject, I made this:
private static string Fetch(string uri, ExpandoObject init)
But Jint use the JsValue and ObjectInstance object internally right? These also have better sematics to work out is what you got passed in was an object or array etc, but this throws an error:
private static string Fetch(string uri, ObjectInstance init)
: 'No valid constructors found'
What would be the recommended way to pass these objects to C#? I want to have as little friction between the js and C# side of the app as I'll be making quite a few calls back and forth (which is why I'm looking at Jint coming from ClearScript)
Some choices:
JsValue
The object is passed as is.
You can't use any other derived type because jint only checks JsValue. To use ObjectInstance, cast it on C# side.
dynamic
This is the equivalent of ExpandoObject.
Jint will convert an ObjectInstance to an ExpandoObject first if the parameter type is other than JsValue.
IDictionary<string,object> or any other generic interface that ExpandoObject implemented
Same as dynamic.
A custom type that the input object is able to convert to.
You could define the object as class or struct, and define the entries as field or property. The name of the member can be capitalized. Notice that this way uses reflection, so it's not effcient.
For instance, you can define it like this:
struct Header
{
public string authorization;
}
class Init
{
public string Method { get; set; }
public Header Headers { get; set; }
}
object
Always works.

Convert a user inputted string to a class that gets cast

I have a string that gets inputted by a user. The string can look like: Button.Minimize or Hyperlink.SomeLink
I need to take the first part of the string and convert it to a class that is located in a dll library. Then I need to cast that as a type.
I have seen countless examples on here but none that show how to convert the string to ANY type. All the examples I have seen are when you know which type you want to convert the string to beforehand.
Basically I need a method that converts a string to any kind of class name. Like: Button, HyperLink, etc...
public static void ClickOn(Step step)
{
string[] kvp = step.Element.Split('.');
var type = kvp[0];
var element = kvp[1];
GetType(type);
var path = MainWin.Get<type>(element); //inputted string would be cast in this line where you see <type>
path.Click();
}
public static Type GetType(string typeName)
{
Type get = Type.GetType(typeName, true);
Object type = (Activator.CreateInstance(get));
return type;
}
If you mean cast as in (string)anObject then there is no way to do this. Casting in this way is a compile time activity that gives the compiler awareness about the type that it is working with. Since what you are describing is essentially a runtime activity, there is nothing that the compiler can do to help you at this point.
If you write a different question that describes the problem you are trying to solve with this in more detail (or change this question), then someone can probably suggest a way to accomplish what you want.
Define interface called IClickablewith a Click method and make all the classes implement that interface. Rename your method GetType to GetClickableObject and make that method return a IClickable. Something like this:
public static void ClickOn(Step step)
{
// get type
string fullClassType = ...;
IClickable obj = MainWin.GetClickableObject(fullClassType);
obj.Click();
}
public static IClickable GetClickableObject(string typeName)
{
Type get = Type.GetType(typeName, true);
IClickable obj = (IClickable)Activator.CreateInstance(get);
return obj;
}
}
interface IClickable
{
void Click();
}
class Button : IClickable
{
//...
}

How to use GetPropertyValueSafely from CommonLibrary.NET?

When using the CommonLibrary.Net, how does one use the GetPropertyValueSafely() function correctly?
I want to do something like this:
public static string APP_TITLE = ComLib.ReflectionHelper.GetPropertyValueSafely(Application.ProductName);
but I need to add a second parameter, and I don't understand enough yet to know what is asked for. Here is the syntax usage from the documentation file:
public static Object GetPropertyValueSafely(
Object obj,
PropertyInfo propInfo
)
This are the parameter requirements:
Parameters obj Type: System..::..Object Object whose property is to be retrieved.
propInfo Type: System.Reflection..::..PropertyInfo Property name.
So what do I put for object? I tried this, too:
public static string APP_TITLE;
ComLib.ReflectionHelper.GetPropertyValueSafely(APP_TITLE, Application.ProductName);
but that's not the answer either.
I also tried this:
public static string APP_TITLE = ComLib.Reflection.ReflectionUtils.GetPropertyValue((object)APP_TITLE, Application.ProductName).ToString();
...which compiles, but it throws a runtime type error from the library.
Thanks for the help (I'm just starting to get this stuff into my head).
Try something like this:
public static readonly string APP_TITLE = (string)ComLib.ReflectionHelper.GetPropertyValueSafely(new object(),
ComLib.Reflection.ReflectionUtils.GetProperty(typeof(Application), "ProductName"));
NB: Technically, passing new object() to the PropertyInfo's GetValue method should throw a TargetException. However, since this is a static property, it seems to work.

How to create extension methods for Types

I am writing an extension method for parsing JSON string for any given type. I wanted to use the method on types instead of instances like many examples we already know, but I somewhat feel it is not supported by Visual Studio. Can someone enlighten me here? The following is the method:
public static T ParseJson<T>(this T t, string str) where T: Type
{
if (string.IsNullOrEmpty(str)) return null;
var serializer = new JavaScriptSerializer();
var obj = serializer.Deserialize<T>(str);
return obj;
}
I want to call the method in this fashion:
var instance = MyClass.ParseJson(text);
Thanks
The short answer is it cannot be done; extension methods need to work on an instance of something.
To use the extension method, you would have to do:
var instance = typeof(MyClass).ParseJson(text);
The token "MyClass" is not a Type instamce intself, but using typeof will get you a Type to operate on. But how is this any better than:
var instance = JsonUtility.ParseJson<MyClass>(text);
Edit: Actually, the code for the extension method still would not do what you wanted. It will always return a "Type" object, not an instance of that Type.
You can't create extension methods that apply to the type itself. They can only be called on instances of a type.
As stated in the accepted answer, you can't. However, provided that you have an extension method that can be called from an instance of T:
public static T ParseJson<T>(this T t, string s)
You could write a utility method like this:
public static T ParseJson<T>(string s)
where T: new()
=> new(T).ParseJson(s);
And call it like this:
var t = Utilities.ParseJson<T>(s);
I am afraid that's the best you can do...
You can create and extension method
public static class MyExtensions
{
public static string Serialize<T>(this T self)
{
return JsonSerializer.Serialize(self);
}
}
And use it like
instance.Serialize();
You don't have to use it like instance.Serialize<Type>(); because most of the time (if not all the time) it can be inferred from the usage.

Dynamically create an object of <Type>

I have a table in my database that I use to manage relationships across my application. it's pretty basic in it's nature - parentType,parentId, childType, childId... all as ints. I've done this setup before, but I did it with a switch/case setup when I had 6 different tables I was trying to link. Now I have 30 tables that I'm trying to do this with and I would like to be able to do this without having to write 30 case entries in my switch command.
Is there a way that I can make reference to a .Net class using a string? I know this isn't valid (because I've tried several variations of this):
Type t = Type.GetType("WebCore.Models.Page");
object page = new t();
I know how to get the Type of an object, but how do I use that on the fly to create a new object?
This link should help:
https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance
Activator.CreateInstance will create an instance of the specified type.
You could wrap that in a generic method like this:
public T GetInstance<T>(string type)
{
return (T)Activator.CreateInstance(Type.GetType(type));
}
If the type is known by the caller, there's a better, faster way than using Activator.CreateInstance: you can instead use a generic constraint on the method that specifies it has a default parameterless constructor.
Doing it this way is type-safe and doesn't require reflection.
T CreateType<T>() where T : new()
{
return new T();
}
public static T GetInstance<T>(params object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}
I would use Activator.CreateInstance() instead of casting, as the Activator has a constructor for generics.
You want to use Activator.CreateInstance.
Here is an example of how it works:
using System;
using System.Runtime.Remoting;
class Program
{
static void Main()
{
ObjectHandle o = Activator.CreateInstance("mscorlib.dll", "System.Int32");
Int32 i = (Int32)o.Unwrap();
}
}
Assuming you have the following type:
public class Counter<T>
{
public T Value { get; set; }
}
and have the assembly qualified name of the type, you can construct it in the following manner:
string typeName = typeof(Counter<>).AssemblyQualifiedName;
Type t = Type.GetType(typeName);
Counter<int> counter =
(Counter<int>)Activator.CreateInstance(
t.MakeGenericType(typeof(int)));
counter.Value++;
Console.WriteLine(counter.Value);
Here is a function I wrote that clones a record of type T, using reflection.
This is a very simple implementation, I did not handle complex types etc.
public static T Clone<T>(T original)
{
T newObject = (T)Activator.CreateInstance(original.GetType());
foreach (var prop in original.GetType().GetProperties())
{
prop.SetValue(newObject, prop.GetValue(original));
}
return newObject;
}
I hope this can help someone.
Assaf

Categories