Get the original nameof(...) of a variable? - c#

I have this
public static class Parameters
{
public static void Required<T>(this T parameter, string paramName) where T : class
{
if (parameter == null)
{
throw new ArgumentNullException(paramName);
}
// ...
}
}
And I use it like:
Parameters.Required(settings, nameof(settings));
Is it possible to get rid of the second parameter and somehow get the original parameter name, from within the Required method? No, right?

You could make the Requred-function accepting a Expression. And from the expression you can read out the name of the member name. It's descriped here.
public static void Required<T>(Expression<Func<T>> parameter) where T : class
{
if (parameter.Compile().Invoke() == null)
{
var caller = ((MemberExpression)parameter.Body).Member.Name;
throw new ArgumentNullException(caller);
}
// ...
}
and call it like this:
Parameters.Required(() => settings);

Related

Can we call a Static method of an Abstract Class using a generic Method? [duplicate]

How do I call a static method from a Type, assuming I know the value of the Type variable and the name of the static method?
public class FooClass {
public static FooMethod() {
//do something
}
}
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod() //works fine
if (t is FooClass) {
t.FooMethod(); //should call FooClass.FooMethod(); compile error
}
}
}
So, given a Type t, the objective is to call FooMethod() on the class that is of Type t. Basically I need to reverse the typeof() operator.
You need to call MethodInfo.Invoke method:
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod(); //works fine
if (t == typeof(FooClass)) {
t.GetMethod("FooMethod").Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
Of course in the above example you might as well call FooClass.FooMethod as there is no point using reflection for that. The following sample makes more sense:
public class BarClass {
public void BarMethod(Type t, string method) {
var methodInfo = t.GetMethod(method);
if (methodInfo != null) {
methodInfo.Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
public class Foo1Class {
static public Foo1Method(){}
}
public class Foo2Class {
static public Foo2Method(){}
}
//Usage
new BarClass().BarMethod(typeof(Foo1Class), "Foo1Method");
new BarClass().BarMethod(typeof(Foo2Class), "Foo2Method");
Note, that as 10 years have passed. Personally, I would add extension method:
public static TR Method<TR>(this Type t, string method, object obj = null, params object[] parameters)
=> (TR)t.GetMethod(method)?.Invoke(obj, parameters);
and then I could call it with:
var result = typeof(Foo1Class).Method<string>(nameof(Foo1Class.Foo1Method));
Check into the MethodInfo class and the GetMethod() methods on Type.
There are a number of different overloads for different situations.

Extending SerializedObject with generic get method

I would like to write an generic extension method for SerializedObject that could be used instead of FindProperty and then accessing whateverValue member, so I would be able to write so.Get<Bool>("myValue") instead of so.FindProperty("myValue").boolValue.
Here is how I would like to solve this if template specialization was a thing in C#:
public static T Get<T>(this SerializedObject so, string name) {
Debug.LogError("Get called with unsuported type!");
}
public static bool Get<bool>(this SerializedObject so, string name) {
return so.FindProperty(name).boolValue;
}
How can something like this be achieved in proper C#? I have also tried to add a System.Type parameter instead of specialization, but then what should the return type of such function be?
I would use a little bit of functional programming. One of the input parameters of the generic function would be another function that would define how the read the property:
public static T Get<T>(this SerializedObject so, string name, Func<SerializedProperty, T> getter) {
var property = so.FindProperty(name);
if (property == null) {
;//handle "not found"
}
return getter(property);
}
A couple of examples of how I would use it:
internal bool ExampleBoolValue(SerializedObject so) {
return so.Get("myBoolValue", (p => p.boolValue));
}
internal int ExampleIntValue(SerializedObject so) {
return so.Get("myIntValue", (p => p.intValue));
}
I don't have Unity installed on this machine so I'm not sure that Unity supports these .NET features.
UPDATE for setter method:
public static void Set(this SerializedObject so, string name, Action<SerializedProperty> setter) {
var property = so.FindProperty(name);
if (property == null) {
;//handle "not found"
}
setter(property);
}
Examples for setting a value:
internal void SetExampleBoolValue(SerializedObject so, bool newValue) {
so.Set("myBoolValue", (p => p.boolValue = newValue));
}
internal void SetExampleIntValue(SerializedObject so, int newValue) {
so.Set("myIntValue", (p => p.intValue = newValue));
}
Action takes 0..n parameters and does not return anything. Func takes 0..n parameters and has to return something.
You can use the magic of generic static to accomplish this.
The first class GetPropertyValue<T> will store your handler based on the type. The static handler initially be set to your "unsupported" message, but the static constructor will call the InitGetPropertyValue class to initialize all the handlers. Because this is within the static constructor of that class, it will only be called once, the first time the class is initialized.
Because the static variable of GetPropertyValue<int>.Get is different than the static variable GetPropertyValue<string>.Get, the handler for your type that you stored previously will be used each subsequent call.
public static class MyExtensions
{
private static class GetPropertyValue<T>
{
static GetPropertyValue()
{
InitGetPropertyValue.Initialize();
}
public static Func<SerializedObject, string, T> Get = (so, name) =>
{
Debug.Print("Get called with unsupported type!");
return default(T);
};
}
private static class InitGetPropertyValue
{
static InitGetPropertyValue()
{
Debug.Print("Initializing property getters");
GetPropertyValue<int>.Get = (so, name) => (int)so.FindProperty(name) ;
GetPropertyValue<Guid>.Get = (so, name) => (Guid)so.FindProperty(name);
GetPropertyValue<string>.Get = (so, name) => so.FindProperty(name).ToString();
}
public static bool Initialize()
{
return true;
}
}
public static T Get<T>(this SerializedObject so, string name)
{
return GetPropertyValue<T>.Get(so, name);
}
}
While not a pretty solution, a working one would be sth like:
public static T Get<T>(this SerializedObject so, string name) {
if (typeof(T) == typeof(bool){
return (T)(object)so.FindProperty(name).boolValue;
}
else if {
...
}
else {
Debug.LogError("Get called with unsuported type!");
}
}
I'd personally go with sth like:
public static bool GetBoolean(this SerializedObject so, string name)
public static int GetInt(this SerializedObject so, string name)
The semantics stays the same, but implementation is cleaner.

Add default behaviour to all public methods

Is it possible in C# to implement a mechanism that will automatically add the default behaviour to each public method of given classes (which implement given interface or have given attribute .. or whatever)?
For example, I have a method:
public void DoSomething(MyClass a) {
if (a != null) {
// Do method body
}
else{
// Throw exception (a argument of type MyClass is null)
}
}
I would like to have this condition automatically added for each attribute without the need for writing it every time for given public methods.
Is there anything (any kind of mechanism) I could use for something like that?
To avoid reflection, you can use a generic method:
public void DoSomething(MyClass a) => MakeSomeStaff(a, () => { /* Do method body */ });
private void MakeSomeStaff<T>(T item, Action action) where T: class
{
if (item == null)
throw new Exception();
action();
}
EDIT: Had an idea that abuses operator overloading, original answer at the bottom:
Use operator overloading to throw on null
public struct Some<T> where T : class {
public T Value { get; }
public Some(T value)
{
if (ReferenceEquals(value, null))
throw new Exception();
Value = value;
}
public override string ToString() => Value.ToString();
public static implicit operator T(Some<T> some) => some.Value;
public static implicit operator Some<T>(T value) => new Some<T>(value);
}
private void DoThingsInternal(string foo) =>
Console.Out.WriteLine($"string len:{foo.Length}");
public void DoStuff(Some<string> foo)
{
DoThingsInternal(foo);
string fooStr = foo;
string fooStrBis = foo.Value;
// do stuff
}
Original answer
You can use an extension method to throw for you
public static class NotNullExt{
public static T Ensure<T>(this T value,string message=null) where T:class
{
if(ReferenceEquals(null,value) throw new Exception(message??"Null value");
return value;
}
}
public void DoSomething(MyClass a) {
a=a.Ensure("foo");
// go ...
}

C# factory construction not working

I am obviously doing something wrong here, but the question is how do i get it working? I got the following code
Note: ParameterEventStreamRef inherits from Parameter, same goes for the StStvariants.
public void DoStuff(Parameter[] parameters)
{
var Parameters = parameters.Select(x => parameterConverterFactory.GetParameterConverter(x).ToJsonClass(x)).ToArray();
}
public class ParameterConverterFactory: IParameterConverterFactory
{
public IStackStateJsonConverter<StStParameter, Parameter> GetParameterConverter(StStParameter arg)
{
if (arg.GetType() == typeof(StStParameterEventStreamRef))
return new JsonParameterEventStreamRefConverter();
throw new InvalidEnumArgumentException(arg.GetType().FullName);
}
public class JsonParameterEventStreamRefConverter : JsonParameterConverter, IStackStateJsonConverter<StStParameterEventStreamRef, ParameterEventStreamRef>
{
public ParameterEventStreamRef ToJsonClass(StStParameterEventStreamRef arg, ParameterEventStreamRef source = null)
{
if (source == null)
source = new ParameterEventStreamRef();
base.ToJsonClass(arg, source);
source.var1 = arg.var1;
source.var2 = arg.var2;
return source;
}
}
public class JsonParameterConverter : JsonNodeConverter, IStackStateJsonConverter<StStParameter, Parameter>
{
public Parameter ToJsonClass(StStParameter arg, Parameter source = null)
{
if (source == null)
source = new Parameter();
source.var0 = arg.var0;
return source;
}
}
Problem is: the factory is returning the correct Converter, but when the converter is called, it is "Skipping" the JsonParameterEventStreamRefConverter and going directly to the JsonParameterConverter. I think the reason for this is a part of the logic is done compile-time, the other run-time.
In DoStuff() you're calling the ToJsonClass() method. Even though that you 'x' could be any descendant from Parameter, the runtime will not know which one it is.
It will look for the ToJsonClass() signature that best matches the signature: ToJsonClass(Parameter). The JsonParamterConverter has a method that matches this exactly, so that's the best match.
You could try replacing the ToJsonClass() in JsonParameterStreamRef with something like this:
public override Parameter ToJsonClass(StStParameter arg, Parameter source = null)
{
if (arg.GetType() == typeof (StStParameterEventStreamRef))
{
return ToJsonClass(arg as StStParameterEventStreamRef, source as ParameterEventStreamRef);
}
return base.ToJsonClass(arg, source); // or throw an exception if this is an error.
}
The following is a working solution to the problem, but if you can come up with a better solution, please.
public Parameter GetConverterFactory_AndDo_ToJsonClass(StStParameter stStParameter)
{
if (stStParameter.GetType() == typeof (StStParameterEventStreamRef))
return new JsonParameterEventStreamRefConverter().ToJsonClass(stStParameter as StStParameterEventStreamRef);
throw new InvalidEnumArgumentException(stStParameter.GetType().FullName);
}

Calling a static method using a Type

How do I call a static method from a Type, assuming I know the value of the Type variable and the name of the static method?
public class FooClass {
public static FooMethod() {
//do something
}
}
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod() //works fine
if (t is FooClass) {
t.FooMethod(); //should call FooClass.FooMethod(); compile error
}
}
}
So, given a Type t, the objective is to call FooMethod() on the class that is of Type t. Basically I need to reverse the typeof() operator.
You need to call MethodInfo.Invoke method:
public class BarClass {
public void BarMethod(Type t) {
FooClass.FooMethod(); //works fine
if (t == typeof(FooClass)) {
t.GetMethod("FooMethod").Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
Of course in the above example you might as well call FooClass.FooMethod as there is no point using reflection for that. The following sample makes more sense:
public class BarClass {
public void BarMethod(Type t, string method) {
var methodInfo = t.GetMethod(method);
if (methodInfo != null) {
methodInfo.Invoke(null, null); // (null, null) means calling static method with no parameters
}
}
}
public class Foo1Class {
static public Foo1Method(){}
}
public class Foo2Class {
static public Foo2Method(){}
}
//Usage
new BarClass().BarMethod(typeof(Foo1Class), "Foo1Method");
new BarClass().BarMethod(typeof(Foo2Class), "Foo2Method");
Note, that as 10 years have passed. Personally, I would add extension method:
public static TR Method<TR>(this Type t, string method, object obj = null, params object[] parameters)
=> (TR)t.GetMethod(method)?.Invoke(obj, parameters);
and then I could call it with:
var result = typeof(Foo1Class).Method<string>(nameof(Foo1Class.Foo1Method));
Check into the MethodInfo class and the GetMethod() methods on Type.
There are a number of different overloads for different situations.

Categories

Resources