I have the following class:
class CrmToRealTypeConverter : IConverter
{
#region IConverter Members
public object Convert<T>(T obj)
{
return Convert(obj);
}
#endregion
private DateTime? Convert(CrmDateTime obj)
{
return obj.IsNull == false ? (DateTime?)obj.UserTime : null;
}
private int? Convert(CrmNumber obj)
{
return obj.IsNull == false ? (int?)obj.Value : null;
}
private decimal? Convert(CrmDecimal obj)
{
return obj.IsNull == false ? (decimal?)obj.Value : null;
}
private double? Convert(CrmDouble obj)
{
return obj.IsNull == false ? (double?)obj.Value : null;
}
private float? Convert(CrmFloat obj)
{
return obj.IsNull == false ? (float?)obj.Value : null;
}
private decimal? Convert(CrmMoney obj)
{
return obj.IsNull == false ? (decimal?)obj.Value : null;
}
private bool? Convert(CrmBoolean obj)
{
return obj.IsNull == false ? (bool?)obj.Value : null;
}
}
I am trying to specialize the Convert method with concreate types.
Currently it just loops recursively in Convert<T>() until a stack overflow occurs.
Polymorphism doesn't work on arguments to a method call. An approach you can use it to check the type of obj, cast it to the specific type and then call the appropriate overload.
public object Convert(object obj)
{
if (obj is CrmDateTime)
return Convert((CrmDateTime)obj);
if (obj is CrmNumber)
return Convert((CrmNumber)obj);
// ...
}
Late-binding doesn't happen the way you think it does; the compiler binds the call to Convert(obj) in thepublic object Convert<T>(T obj) method to the same method (recursive call). The behaviour you appear to be expecting is that the CLR will dynamically choose the most appropriate overload to execute at run-time, but it doesn't work that way. Try something like this instead:
public object Convert<T>(T obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
var cdt = obj as CrmDateTime;
if (cdt != null)
return Convert(cdt); // bound at compile-time to DateTime? Convert(CrmDateTime)
var cn = obj as CrmNumber;
if (cn != null)
return Convert(cn); // bound at compile-time to int? Convert(CrmNumber)
// ...
throw new NotSupportedException("Cannot convert " + obj.GetType());
}
If you prefer, you can use reflection here. Such a solution would look something like:
// Making the method generic doesn't really help
public object Convert(object obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
// Target method is always a private, instance method
var bFlags = BindingFlags.Instance | BindingFlags.NonPublic;
// ..which takes a parameter of the obj's type.
var parameterTypes = new[] { obj.GetType() };
// Get a MethodInfo instance that represents the correct overload
var method = typeof(CrmToRealTypeConverter)
.GetMethod("Convert", bFlags, null, parameterTypes, null);
if (method == null)
throw new NotSupportedException("Cannot convert " + obj.GetType());
// Invoke the method with the forwarded argument
return method.Invoke(this, new object[] { obj });
}
The model you should follow is the model in the .Net Convert class, there is no reason for you to make the constructor a generic, it brings nothing to the table. Change the convert routines to static methods and the class itself to static:
static class CrmToRealTypeConverter : IConverter
{
#region IConverter Members
public static DateTime? Convert(CrmDateTime obj)
{
return obj.IsNull == false ? (DateTime?)obj.UserTime : null;
}
public static int? Convert(CrmNumber obj)
{
return obj.IsNull == false ? (int?)obj.Value : null;
}
public static decimal? Convert(CrmDecimal obj)
{
return obj.IsNull == false ? (decimal?)obj.Value : null;
}
public static double? Convert(CrmDouble obj)
{
return obj.IsNull == false ? (double?)obj.Value : null;
}
public static float? Convert(CrmFloat obj)
{
return obj.IsNull == false ? (float?)obj.Value : null;
}
public static decimal? Convert(CrmMoney obj)
{
return obj.IsNull == false ? (decimal?)obj.Value : null;
}
public static bool? Convert(CrmBoolean obj)
{
return obj.IsNull == false ? (bool?)obj.Value : null;
}
}
Then when you call one of the convert methods the compiler will select the proper overload to call:
CrmDateTime crmDate;
CrmToRealTypeConverter.Convert(crmDate); // Will call the static DateTime? Convert(CrmDateTime obj) overload
// or
CrmNumber crmNum;
CrmToRealTypeConverter.Convert(crmNum); // Will call the static int? Convert(CrmNumber obj) overload
// and so on...
Edit:
If you do the following:
CrmFloat num;
// ...
Object obj = num;
CrmToRealTypeConverter.Convert(obj);
it will not work as the compiler doesn't know the type to match the overload. You would have to cast it and it will work:
CrmToRealTypeConverter.Convert((CrmFloat)obj);
This occurs because the compiler doesn't know the generic type of T until runtime and binds the call to T = System.Object at compile-time, and the only function suitable to take a System.Object is that function itself. However, in .NET 4, you can use the dynamic keyword to cause the runtime to select the correct overload dynamically based on T at runtime, which is what you are looking to happen.
Simple example:
class Main {
static void somefunction(System.String str)
{
System.Console.WriteLine("In String overload");
}
static void somefunction(System.Object obj)
{
System.Console.WriteLine("In Object overload");
}
static void somegenericfunction<T>(T object)
{
somefunction(object);
}
static void dynamicfunction<T>(dynamic T object)
{
somefunction(object);
}
static void main(System.String[] args)
{
somegenericfunction("A string"); // Calls Object overload, even though it's a String.
dynamicfunction("A string"); // Calls String overload
}
}
Note that I don't actually have my compiler on hand and this might not compile literally, but close enough.
Related
I'm working with RPC(protobuf-remote) and I need to do some checking in case the other end(server) is down. Let's say I've lot's of RPC methods, like:
public FirstObj First(string one, string two)
{
if (rpc == null)
return (FirstObj)Activator.CreateInstance(typeof(FirstObj));
return rpc.First(one, two);
}
public SecondObj Second(string one)
{
if (rpc == null)
return (SecondObj)Activator.CreateInstance(typeof(SecondObj));
return rpc.Second(one);
}
public ThirdObj Third()
{
if (rpc == null)
return (ThirdObj)Activator.CreateInstance(typeof(ThirdObj));
return rpc.Third();
}
Is there anyway to change this repetitive null-checking code? So I could write something like:
public FirstObj First(string one, string two)
{
return rpc.First(one, two);
}
Which would do null-checking and would create object by it's type if RPC server is down, so I will get default values of required object.
You could create such extension method:
public static class RpcExtension
{
public static T GetObject<T>(this RPC rpc, Func<RPC, T> func)
where T: class , new ()
{
if (rpc == null)
{
return Activator.CreateInstance<T>();
}
return func(rpc);
}
}
for this usage:
var first = rpc.GetObject(r => r.First(a, b));
You can simplify your code with a generic method:
private static T Make<T>() {
return (T)Activator.CreateInstance(typeof(T));
}
public FirstObj First(string one, string two) {
return rpc == null ? Make<FirstObj>() : rpc.First(one, two);
}
public SecondObj Second(string one) {
return rpc == null ? Make<SecondObj>() : rpc.Second(one);
}
public ThirdObj Third() {
return rpc == null ? Make<ThirdObj>() : rpc.Third();
}
If FirstObj, SecondObj, and ThirdObj types are all classes, not structs or primitives, and rpc never returns null for them, you can do this:
public static T RpcOrDefault<T>(T obj) where T : class {
return obj ?? (T)Activator.CreateInstance(typeof(T));
}
and call it
FirstObj first = RpcOrDefault(rpc?.First(one, two));
// ^
Note the ? in ?. which shields you from null reference exceptions.
I came across a problem which for me is a bit tricky..
I have a Cache helper class that is generic..s...
I'm thinking of removing the casting just before the if statement and cast the object when returning it at the end...?
If you're concerned that the obj variable can be null after function.Invoke() then you can test and use the default operator.
public static class CacheHelper<T>
{
public static T Get(string key, Func<T> function) {
var obj = HttpContext.Current.Cache[key]; // removed the cast
if (obj == null)
{
obj = function.Invoke();
if (obj == null)
{
return default(T);
}
HttpContext.Current.Cache.Add(key, obj, null, DateTime.Now.AddMinutes(3), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Normal, null);
}
return (T)obj; // now obj won't be null, but it might still be a different type
}
}
Which method of DynamicObject do I have to override in order to get a different behavior (in the dynamic class) based on the context in which the instance is used?
Here is an example of what I am trying to accomplish:
class DynamicTest : DynamicObject
{
public DynamicTest(string xyz)
{
_xyz = xyz;
}
private string _xyz;
//TODO: what do I need to implement to get required behaviour?
}
class Program
{
static void Main(string[] args)
{
dynamic foo = new DynamicTest("test);
if (foo) // treat foo as boolean
{ // jump in here when _xyz of foo has a value
System.Console.WriteLine(foo); //treat foo as string
}
else
{ // jump in here when _xyz of foo is null
System.Console.WriteLine("No Value In Object");
}
}
}
I don't know why are you trying to do this and I will definitely NOT will recommend doing this, but you can override TryConvert method on DynamicObject like:
class DynamicTest : DynamicObject
{
public DynamicTest(string xyz)
{
_xyz = xyz;
}
private string _xyz;
public override bool TryConvert(ConvertBinder binder, out Object result)
{
Console.WriteLine ("TryConvert was called");
Console.WriteLine ("Is explicit: "+binder.Explicit);
if(binder.Type == typeof(bool))
{
result = true;
return true;
}
else if(binder.Type == typeof(string))
{
result = _xyz;
return true;
}
result = null;
return false;
}
public override string ToString()
{
return _xyz;
}
}
Now there are some issues: ToString is required for Console.WriteLine, it doesn't try to convert if no implicit convertions exist (because WriteLine is overloaded), so it calls ToString. Implicit and explicit conversions to bool pass, but if you use foo inside if - you will get RuntimeBinderException: Cannot implicitly convert type 'DynamicTest' to 'bool'.
Examples:
dynamic foo = new DynamicTest("test:");
bool boolFoo = foo; //passes, TryConvert is called with `binder.Explicit` == false
bool boolFoo1 = (bool)foo; //passes, TryConvert is called with `binder.Explicit` == true
if(foo) //throws RuntimeBinderException
I think implicit operator can help you
Example code:
class DynamicTest : DynamicObject
{
public DynamicTest(string xyz)
{
_xyz = xyz;
}
private string _xyz;
public static implicit operator bool(DynamicTest rhs)
{
return rhs._xyz != null;
}
public static implicit operator string(DynamicTest rhs)
{
return rhs._xyz;
}
//TODO: what to override to get required behaviour
}
class Program
{
static void Main(string[] args)
{
dynamic foo = new DynamicTest("test");
if (foo) // treat foo as boolean
{ // jump in here when _xyz of foo has a value
System.Console.WriteLine((string)foo); //treat foo as string //Importat: (string)foo to go operatorstring
}
else
{ // jump in here when _xyz of foo is null
System.Console.WriteLine("No Value In Object");
}
}
}
is there any way to do this on a class and still retain the capability to detect whether a variable of the Type is null ? I can do this for structs, (cause struct can't really be null, with a struct, instead of comparing x with null, you use a separate method caleld IsNull or HasValue... but you can't use that technique with a class cause when the class variable is null, of course, you can't call such an instance method on it !
public class myClass: IEquatable<myClass>
{
public int IntValue { get; set; }
public static bool operator ==(myClass cA, myClass cB)
{ return cA is myClass && cB is myClass && cB.Equals(cA); }
public static bool operator !=(myClass cA, myClass cB)
{ return !(cA == cB); }
public override bool Equals(object o)
{ return o is myClass && this == (myClass)o; }
public override bool Equals(myClass o)
{ return IntValue == o.IntValue; }
}
but when I go:
myClass x;
if (x != null) // this returns false when it should be true
{
//code to execute with x here
}
For what it's worth, the only reason I want this to be a class is because it participates in a simple inheritance relationship. This is an immutable class, and in effect what I am trying to do here is code it so it can behave like an immutable and nullable class, exactly like an immutable, nullable struct behaves (such as Nullable<int> or Nullable<float> etc.
That's why IsNull should be a static method taking a parameter. string.IsNullOrEmpty is a good example. After that, nothing prevents you from making it an extension method.
public class MyClass
{
public static bool IsNull(MyClass other)
{ return ReferenceEquals(other, null); }
public static bool HasValue(MyClass other)
{ return !IsNull(other); }
// other code
}
public static class MyClassExtension
{
public static bool IsNull(this MyClass myClass)
{
return MyClass.IsNull(myClass);
}
}
This will let you do the following without throwing:
MyClass myClass = null;
if(myClass.IsNull())
{
//...
}
If you're not initializing x so it is null, you need to do this
myClass x = new myClass();
if (x != null) {/* is true */}
You can always use:
ReferenceEquals(x, null)
this returns a boolean value showing whether x is null.
You should not do this at all.
You should only do this for an immutable class, if you really must. And then,
You should follow the guidelines
public class myClass: IEquatable<myClass>
{
public static bool operator ==(myClass cA, myClass cB)
{ return (cB == null && cA = null) || (cA is myClass && cB is myClass && cB.Equals(cA)); }
}
Why not just override GetHashCode and Equals?
when you override them both it allows you do do both == and != very easily..
I would like to perform a test if an object is of a generic type. I've tried the following without success:
public bool Test()
{
List<int> list = new List<int>();
return list.GetType() == typeof(List<>);
}
What am I doing wrong and how do I perform this test?
If you want to check if it's an instance of a generic type:
return list.GetType().IsGenericType;
If you want to check if it's a generic List<T>:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
As Jon points out, this checks the exact type equivalence. Returning false doesn't necessarily mean list is List<T> returns false (i.e. the object cannot be assigned to a List<T> variable).
I assume that you don't just want to know if the type is generic, but if an object is an instance of a particular generic type, without knowing the type arguments.
It's not terribly simple, unfortunately. It's not too bad if the generic type is a class (as it is in this case) but it's harder for interfaces. Here's the code for a class:
using System;
using System.Collections.Generic;
using System.Reflection;
class Test
{
static bool IsInstanceOfGenericType(Type genericType, object instance)
{
Type type = instance.GetType();
while (type != null)
{
if (type.IsGenericType &&
type.GetGenericTypeDefinition() == genericType)
{
return true;
}
type = type.BaseType;
}
return false;
}
static void Main(string[] args)
{
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new List<string>()));
// False
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new string[0]));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList()));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList<int>()));
}
class SubList : List<string>
{
}
class SubList<T> : List<T>
{
}
}
EDIT: As noted in comments, this may work for interfaces:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
I have a sneaking suspicion there may be some awkward edge cases around this, but I can't find one it fails for right now.
These are my two favorite extension methods that cover most edge cases of generic type checking:
Works with:
Multiple (generic) interfaces
Multiple (generic) base classes
Has an overload that will 'out' the specific generic type if it returns true (see unit test for samples):
public static bool IsOfGenericType(this Type typeToCheck, Type genericType)
{
Type concreteType;
return typeToCheck.IsOfGenericType(genericType, out concreteType);
}
public static bool IsOfGenericType(this Type typeToCheck, Type genericType, out Type concreteGenericType)
{
while (true)
{
concreteGenericType = null;
if (genericType == null)
throw new ArgumentNullException(nameof(genericType));
if (!genericType.IsGenericTypeDefinition)
throw new ArgumentException("The definition needs to be a GenericTypeDefinition", nameof(genericType));
if (typeToCheck == null || typeToCheck == typeof(object))
return false;
if (typeToCheck == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if ((typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck) == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if (genericType.IsInterface)
foreach (var i in typeToCheck.GetInterfaces())
if (i.IsOfGenericType(genericType, out concreteGenericType))
return true;
typeToCheck = typeToCheck.BaseType;
}
}
Here's a test to demonstrate the (basic) functionality:
[Test]
public void SimpleGenericInterfaces()
{
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>)));
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>)));
Type concreteType;
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>), out concreteType));
Assert.AreEqual(typeof(IEnumerable<string>), concreteType);
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>), out concreteType));
Assert.AreEqual(typeof(IQueryable<string>), concreteType);
}
You can use shorter code using dynamic althougth this may be slower than pure reflection:
public static class Extension
{
public static bool IsGenericList(this object o)
{
return IsGeneric((dynamic)o);
}
public static bool IsGeneric<T>(List<T> o)
{
return true;
}
public static bool IsGeneric( object o)
{
return false;
}
}
var l = new List<int>();
l.IsGenericList().Should().BeTrue();
var o = new object();
o.IsGenericList().Should().BeFalse();
return list.GetType().IsGenericType;
public static string WhatIsMyType<T>()
{
return typeof(T).NameWithGenerics();
}
public static string NameWithGenerics(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type.IsArray)
return $"{type.GetElementType()?.Name}[]";
if (!type.IsGenericType)
return type.Name;
var name = type.GetGenericTypeDefinition().Name;
var index = name.IndexOf('`');
var newName = index == -1 ? name : name.Substring(0, index);
var list = type.GetGenericArguments().Select(NameWithGenerics).ToList();
return $"{newName}<{string.Join(",", list)}>";
}
Now test with this:
Console.WriteLine(WhatIsMyType<IEnumerable<string>>());
Console.WriteLine(WhatIsMyType<List<int>>());
Console.WriteLine(WhatIsMyType<IList<int>>());
Console.WriteLine(WhatIsMyType<List<ContentBlob>>());
Console.WriteLine(WhatIsMyType<int[]>());
Console.WriteLine(WhatIsMyType<ContentBlob>());
Console.WriteLine(WhatIsMyType<Dictionary<string, Dictionary<int, int>>>());
and you will get
IEnumerable<String>
List<Int32>
IList<Int32>
List<ContentBlob>
Int32[]
ContentBlob
Dictionary<String,Dictionary<Int32,Int32>>