Add default behaviour to all public methods - c#

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 ...
}

Related

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.

Generic class for enumerations - casting issue

I want to write a generic class that accepts enumerations. Since this class is intended to implement some interfaces, the main aim is to be able to treat enumerations as other objects implementing those interfaces(e.g. for list extensions, etc). Hence, for a sample enum
public enum QEnum : int
{
xlNoValue = 0,
xlSomeValue = 1
}
public static class QEnumExtensions
{
public static string toString(this QEnum xThis)
{
...
}
public static QEnum toEnum(this string xThis)
{
...
}
}
I would like to declare a generic class such as
public class QEnumHolder<T> where T : struct, IConvertible
{
private T mxVal = default(T);
public QEnumHolder()
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
}
public QEnumHolder(T xVal)
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
mxVal = xVal;
}
static public implicit operator QEnumHolder<T>(T xVal)
{
return new QEnumHolder<T>(xVal);
}
static public implicit operator T(QEnumHolder<T> xVal)
{
return (T)xVal.mxVal;
}
public string toString()
{
if (mxVal is QEnum) return ((QEnum)Convert.ToInt32(mxVal)).toString();
...
}
public void fromString(string xString)
{
if (mxVal is QEnum)
mxVal = (???)xString.toEnum(); // problem
}
}
All of the enumerations that we use implement
toString() function which returns a "nice" string that can go into comboBoxes, etc
conversion of string to enumeration, as above
hence the structure of toString/toEnum is pretty much given. The problem is with the last code line marked "problem". I have no idea how to tell the compiler that in this branch, the return type of toEnum() and T will be the same.
I tried to circumvent the problem by declaring mxVal as int and using Convert.ToInt32 everywhere. However, then I run into problem in the operator T where the compiler has objections against converting int to a T (the compiler can't know that T will be enum, hence I can't use none of the "int to enum conversion" discussions here on SO).
A better design would be to use some naming convention, put all your enum extension methods in one and the same static class, and bind these functions inside your holder class static constructor. Something like this:
public static partial class MyEnumExtensions
{
public static MyEnumHolder<T> ToHolder<T>(this T source)
where T : struct, IConvertible
{
return new MyEnumHolder<T>(source);
}
}
public class MyEnumHolder<T> where T : struct, IConvertible
{
static readonly Func<T, string> toStringFunc;
static readonly Func<string, T> toEnumFunc;
static MyEnumHolder()
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
// Use your naming conventions
var name = typeof(T).Name;
toStringFunc = (Func<T, string>)Delegate.CreateDelegate(typeof(Func<T, string>),
typeof(MyEnumExtensions).GetMethod("toString", new[] { typeof(T) }));
toEnumFunc = (Func<string, T>)Delegate.CreateDelegate(typeof(Func<string, T>),
typeof(MyEnumExtensions).GetMethod("to" + name, new[] { typeof(string) }));
}
private T value;
public MyEnumHolder() { value = default(T); }
public MyEnumHolder(T value) { this.value = value; }
static public implicit operator MyEnumHolder<T>(T x) { return new MyEnumHolder<T>(x); }
static public implicit operator T(MyEnumHolder<T> x) { return x.value; }
public string toString()
{
return toStringFunc(value);
}
public void fromString(string xString)
{
value = toEnumFunc(xString);
}
}
Sample enum definitions (could be in separate files, but must be inside the same project):
public enum MyEnumA { A1, A2, A3 }
partial class MyEnumExtensions
{
public static string toString(this MyEnumA x)
{
//...
return x.ToString();
}
public static MyEnumA toMyEnumA(this string x)
{
//...
return (MyEnumA)Enum.Parse(typeof(MyEnumA), x);
}
}
and
public enum MyEnumB { B1, B2, B3 }
partial class MyEnumExtensions
{
public static string toString(this MyEnumB x)
{
//...
return x.ToString();
}
public static MyEnumB toMyEnumB(this string x)
{
//...
return (MyEnumB)Enum.Parse(typeof(MyEnumB), x);
}
}
test:
var a = MyEnumA.A1.ToHolder();
var sA = a.toString();
a.fromString("A2");
var b = MyEnumB.B2.ToHolder();
var sB = b.toString();
b.fromString("B1");
mxVal = (T)(object)xString.toEnum();

implicit or explicit conversion from T to T[]

Is there a way to implement a generic implicit or explicit converter for anything to an array of anything, something like this:
public static implicit operator T[](T objToConvert)
{
return new T[] { objToConvert };
}
No. The closest I can think of is an extension method:
public static T[] AsArray<T>(this T instance)
{
return new T[]{instance};
}
Use as:
var myArray = myInstnace.AsArray();
Note that you can omit the type name from the array constructor, which means the syntax is fairly clean, even with a long type name:
ReallyLongAndAwkwardTypeName value;
MethodThatTakesArray(new[] {value});
Operator overloading methods have to live inside the class they are overriding operators for (one side or the other). Since "T" is not defined, I don't see how this can be accomplished.
You can do it using normal method:
public static T[] ToArray<T>(T objToConvert) {
return new T[] { objToConvert };
}
I don't think you can define generics operator. Note, anyway, that the compiler is sufficient cleaver to guess the type of the generic param, so you can use:
var aString="";
var aStringArray=ToArray(aString);
aStringArray is defined as a string array even if you don't specify the generic param.
I was trying to think of situations where you might really use an implicit conversion to array. I started to wonder if many of the situations where you would want to do this could be alleviated by use of the params keyword.
The main situation that I could think of was that you had a single item of something and wanted to pass it to a function that takes an array as a parameter:
static void Main(string[] args)
{
string x = "I'm just a poor variable. Nobody loves me.";
Stickler.IOnlyTakeArrays_Rawr111(x); // won't go in! square peg, round hole, etc.
// *sigh* fine.
Stickler.IOnlyTakeArrays_Rawr111(new[] { x });
}
class Stickler
{
public static void IOnlyTakeArrays_Rawr111(string[] yum)
{
// ...
}
}
Hopefully in this situation the author of the method that you want to call has choosen to use the params keyword to allow you to pass your variable without wrapping it in an array:
class DataConcierge
{
public static T Create<T>(int id)
{
// ...
}
public static void Save<T>(params T[] items)
{
// ...
}
}
static void Main(string[] args)
{
var customer = DataConcierge.Create<Customer>(123);
// ...
DataConcierge.Save(customer); // this works!
//----------------------------------------------------
// or
//----------------------------------------------------
var customers = new Customer[]
{
DataConcierge.Create<Customer>(123),
DataConcierge.Create<Customer>(234),
DataConcierge.Create<Customer>(345),
};
// ...
DataConcierge.Save(customers); // this works too!
}
Of course, this doesn't really help you in situations where you need convert a variable to a single item array but not as a parameter to a method or in situations where the author of the method didn't use the params keyword.
But what kind of situation would the former be? Assigning an array to a property? Psh. How often does that happen?
And the latter? If the author didn't use the params keyword when they could have, then send them an email complaining about it. If the author is yourself, feel free to be extra belligerent in the email.
Hopefully you can tell that I'm being facetious. Seriously, though, are there any other common usage situations that you can think of where the params keyword would not be applicable?
** Disclaimer: I don't advocate excessive use of the params keyword. Use it if you think you should, but don't take my post to mean that you should always use the params keyword whenever you can.
In the past I've used the concept of a "Conductor" (my own name for it), which is just a class/struct that provides access to an underlying value.
The concept is useful for abstracting the access to a particular value retrieved from somewhere. For example, if you wanted to abstract access to a particular value in a dictionary, you could create a Conductor object that held a reference to the dictionary and the appropriate key for that value. You can also use this concept to easily implement rollback for serializable classes or for value types, though for that you'd need to add Rollback and Commit methods to the Conductor class/struct.
Below is an example of how you can use implicit conversions from T to Conductor and from Conductor to T[] in order to (sort of) achieve what you want.
static void Main(string[] args)
{
// implicit conversion here from Customer to Conductor<Customer>
Conductor<Customer> conductor = DataConcierge.Create<Customer>(123);
if (conductor.HasValue)
{
Console.WriteLine("I got a customer with Id {0}!", conductor.Value.Id);
// implicit conversion here from Conductor<Customer> to Customer[]
DataConcierge.Save<Customer>(conductor);
}
}
public struct Conductor<T> : IConductor<T>, IEquatable<T>, IEquatable<Conductor<T>>, IEquatable<IConductor<T>>
{
private T _Value;
public Conductor(T value)
{
this._Value = value;
}
public T Value
{
get { return this._Value; }
set { this._Value = value; }
}
public bool HasValue
{
get { return this._Value != null; }
}
public T GetValueOrDefault()
{
if (this.HasValue)
return this.Value;
else
return default(T);
}
public T GetValueOrDefault(T #default)
{
if (this.HasValue)
return this.Value;
else
return #default;
}
public bool TryGetValue(out T value)
{
if (this.HasValue)
{
value = this.Value;
return true;
}
else
{
value = default(T);
return false;
}
}
public T[] AsArray()
{
return new T[] { this._Value };
}
public static implicit operator Conductor<T>(T value)
{
return new Conductor<T>(value);
}
public static implicit operator T(Conductor<T> conductor)
{
return conductor.Value;
}
public static implicit operator T[](Conductor<T> conductor)
{
return conductor.AsArray();
}
public bool Equals(T other)
{
var otherEquatable = other as IEquatable<T>;
if (otherEquatable != null)
return otherEquatable.Equals(this.Value);
else
return object.Equals(this.Value, other);
}
public bool Equals(Conductor<T> other)
{
if (other.HasValue)
return this.Equals(other.Value);
else
return !this.HasValue;
}
public bool Equals(IConductor<T> other)
{
if (other != null && other.HasValue)
return this.Equals(other.Value);
else
return !this.HasValue;
}
public override bool Equals(object obj)
{
if (obj == null)
return !this.HasValue;
var conductor = obj as IConductor<T>;
if (conductor != null)
{
if (conductor.HasValue)
return this.Equals(conductor.Value);
else
return !this.HasValue;
}
return object.Equals(this.Value, obj);
}
public override int GetHashCode()
{
if (this.HasValue)
return this.Value.GetHashCode();
else
return 0;
}
public override string ToString()
{
if (this.HasValue)
return this.Value.ToString();
else
return null;
}
}

Can a method be overriden with a lambda function

Is there any way to override a class method with a lambda function?
For example with a class definition of
class MyClass {
public virtual void MyMethod(int x) {
throw new NotImplementedException();
}
}
Is there anyway to do:
MyClass myObj = new MyClass();
myObj.MyMethod = (x) => { Console.WriteLine(x); };
Chris is right that methods cannot be used like variables. However, you could do something like this:
class MyClass {
public Action<int> MyAction = x => { throw new NotImplementedException() };
}
To allow the action to be overridden:
MyClass myObj = new MyClass();
myObj.MyAction = (x) => { Console.WriteLine(x); };
No. However if you declare the method as a lambda in the first place, you can set it, though I would try to do that at initialization time.
class MyClass {
public MyClass(Action<int> myMethod)
{
this.MyMethod = myMethod ?? x => { };
}
public readonly Action<int> MyMethod;
}
This however cannot implement an interface that has a MyMethod declared, unless the interface specifies a lambda property.
F# has object expressions, which allow you to compose an object out of lambdas. I hope at some point this is part of c#.
No. Methods cannot be used like variables.
If you were using JavaScript, then yes, you could do that.
You can write this code:
MyClass myObj = new MyClass();
myObj.TheAction = x => Console.WriteLine(x);
myObj.DoAction(3);
If you define MyClass in this way:
class MyClass
{
public Action<int> TheAction {get;set;}
public void DoAction(int x)
{
if (TheAction != null)
{
TheAction(x);
}
}
}
But that shouldn't be too surprising.
Not directly, but with a little code it's doable.
public class MyBase
{
public virtual int Convert(string s)
{
return System.Convert.ToInt32(s);
}
}
public class Derived : MyBase
{
public Func<string, int> ConvertFunc { get; set; }
public override int Convert(string s)
{
if (ConvertFunc != null)
return ConvertFunc(s);
return base.Convert(s);
}
}
then you could have code
Derived d = new Derived();
int resultBase = d.Convert("1234");
d.ConvertFunc = (o) => { return -1 * Convert.ToInt32(o); };
int resultCustom = d.Convert("1234");
Depending on what you want to do, there are many ways to solve this problem.
A good starting point is to make a delegate (e.g. Action) property that is gettable and settable. You can then have a method which delegates to that action property, or simply call it directly in client code. This opens up a lot of other options, such as making the action property private settable (perhaps providing a constructor to set it), etc.
E.g.
class Program
{
static void Main(string[] args)
{
Foo myfoo = new Foo();
myfoo.MethodCall();
myfoo.DelegateAction = () => Console.WriteLine("Do something.");
myfoo.MethodCall();
myfoo.DelegateAction();
}
}
public class Foo
{
public void MethodCall()
{
if (this.DelegateAction != null)
{
this.DelegateAction();
}
}
public Action DelegateAction { get; set; }
}

ambiguous/conflicting constructors in generic class

I've got a generic class:
public class BaseFieldValue<T>
{
public BaseFieldValue()
{
//...
}
public BaseFieldValue(string value)
{
//...
}
public BaseFieldValue(T value)
{
//...
}
}
Fine. Except...
var myValue = new BaseFieldValue<string>("hello");
Oops. The undesired constructor is called. There's a number of ways to address the problem. What's the best solution?
I would probably make one of the overloads into a factory method:
public static BaseFieldValue<T> Parse(string value){}
You could do the following:
public class BaseFieldValue<T>
{
public struct Special
{
internal string m_value;
public Special(string value)
{
m_value = value;
}
}
public BaseFieldValue()
{
//...
}
public BaseFieldValue(Special value)
{
//...
}
public BaseFieldValue(T value)
{
//...
}
}
... or, you could add an extra ignored boolean parameter to your special constructor, just to disambiguate it.
Couldn't make Type Contraints do what I wanted, so my workaround is removing the ambiguous constructor while retaining the special case for string:
public class BaseFieldValue<T>
{
public BaseFieldValue()
{
//...
}
public BaseFieldValue(T value)
{
//however many things you need to test for here
if (typeof(T) == typeof(string))
{
SpecialBaseFieldValue(value.ToString());
}
else
{
//everything else
}
//...
}
private void SpecialBaseFieldValue(string value)
{
//...
}
}
A nasty hack, but probably no worse than any of the alternatives:
public class BaseFieldValue<T>
{
public BaseFieldValue()
{
// ...
}
public BaseFieldValue(StringWrapper value)
{
// ...
}
public BaseFieldValue(T value)
{
// ...
}
public class StringWrapper
{
private string _value;
public static implicit operator string(StringWrapper sw)
{
return sw._value;
}
public static implicit operator StringWrapper(string s)
{
return new StringWrapper { _value = s };
}
}
}
And now it can be used as you need:
// call the generic constructor
var myValue = new BaseFieldValue<string>("hello");
// call the string constructor
var myValue = new BaseFieldValue<int>("hello");
May be you can try thi:
var myValue = new BaseFieldValue<Object>("hello" as Object);

Categories

Resources