private static T ConvertType <T>(object value) { var conversionType = typeof(T); if (value is null || conversionType == typeof(object)) { return((T)value); } Type valueType = value.GetType(); if (valueType == conversionType || conversionType.IsAssignableFrom(valueType)) { return((T)value); } // Finally we try to duck type return(DuckType.Create <T>(value)); }
public void DuckTypeAbstractTest() { lock (Runner.Locker) { Console.WriteLine(); var tObject = new TestObject { Name = "Tony", Value = "Redondo" }; var iObj = tObject.DuckAs <AbstractDuckTestObject>(); var tTmp = Activator.CreateInstance(iObj.Type !); var tObj = tTmp !.DuckAs <AbstractDuckTestName>(); tObj.Name = "My new setter"; var nObj = tTmp !.DuckAs <AbstractDuckTestNoInherits>(); Console.WriteLine($"Type = {iObj.Type}"); Console.WriteLine($"Version = {iObj.AssemblyVersion}"); Console.WriteLine(); Assert.Equal(tObject.Status, iObj.Status); Runner.RunF("Get Public Property", () => tObject.Name, () => iObj.Name); Runner.RunA("Set Public Property", () => tObject.Name = "SetTest", () => iObj.Name = "SetTest"); Runner.RunF("Get Public Static Property", () => TestObject.PublicStaticProp, () => iObj.PublicStaticProp); Runner.RunA("Set Public Static Property", () => TestObject.PublicStaticProp = "PSP", () => _ = iObj.PublicStaticProp = "PSP"); Runner.RunF("Get Private Static Property", null, () => iObj.PrivateStaticProp); Runner.RunF("Get Self Property as DuckType", () => DuckType.Create <AbstractDuckTestName>(tObject.Self), () => iObj.Self); Runner.RunA("Set Self Property as DuckType", () => tObject.Self = (TestObject)tObj.Instance, () => iObj.Self = tObj); Runner.RunF("Get Public Property. Float->Int conversion", () => (int)tObject.Number, () => iObj.Number); Runner.RunA("Set Public Property. Int->Float conversion", () => tObject.Number = (int)42, () => iObj.Number = 42); Runner.RunF("Get Public Property. Enum->Int conversion", () => (int)tObject.MyEnumValue, () => iObj.MyEnumValue); Runner.RunA("Set Public Property. Int->Enum conversion", () => tObject.MyEnumValue = (TestEnum)0, () => iObj.MyEnumValue = 0); Runner.RunF("Get Public Property. Enum->Enum conversion", () => (TestEnum2)(int)tObject.MyEnumValue, () => iObj.MyEnumValueConverted); Runner.RunF("Get Public Property. Float->Object conversion", () => (object)tObject.Number, () => iObj.NumberObject); Runner.RunA("Set Public Property. Object(Float)->Float conversion", () => tObject.Number = (float)(object)51f, () => iObj.NumberObject = 51f); Runner.RunA("Set Public Property. Object(Int)->Float conversion", () => tObject.Number = (float)Convert.ChangeType(42, typeof(float)), () => iObj.NumberObject = 42); Runner.RunF("Get Public Property. IList conversion", () => (IList)tObject.MyList, () => iObj.MyList); Runner.RunF("Get Indexer Property", () => tObject[50], () => iObj[50]); Runner.RunA("Set Indexer Property", () => tObject[51] = "next one", () => iObj[51] = "next one with duck"); Runner.RunF("Generic Method Call", () => tObject.GetDefault <Guid>(), () => iObj.GetDefault <Guid>()); Console.WriteLine(); Console.WriteLine(); Runner.RunF("Get Public Field", () => tObject.Value, () => iObj.Value); Runner.RunA("Set Public Field", () => tObject.Value = "SetTest", () => iObj.Value = "SetTest"); Runner.RunF("Get Public Static Field", () => TestObject._publicStaticField, () => iObj.PublicStaticField); Runner.RunA("Set Public Static Field", () => TestObject._publicStaticField = "PSP", () => _ = iObj.PublicStaticField = "PSP"); Runner.RunF("Get Private Field", null, () => iObj.PrivateValue); Runner.RunA("Set Private Field", null, () => iObj.PrivateValue = "PrivateValue"); Runner.RunF("Get Self Field as DuckType", () => tObject.ValueSelf.DuckAs <AbstractDuckTestName>(), () => iObj.ValueSelf); Runner.RunA("Set Self Field as DuckType", () => tObject.ValueSelf = (TestObject)tObj.Instance, () => iObj.ValueSelf = tObj); Runner.RunF("Get Private Static Field", null, () => iObj.PrivateStaticField); Runner.RunF("Get Public Field. Float->Int conversion", () => (int)tObject.FieldNumber, () => iObj.FieldNumberInteger); Runner.RunA("Set Public Field. Int->Float conversion", () => tObject.FieldNumber = (int)42, () => iObj.FieldNumberInteger = 42); Runner.RunF("Get Public Field. Enum->Int conversion", () => (int)tObject.MyEnumFieldValue, () => iObj.MyEnumFieldValue); Runner.RunA("Set Public Field. Int->Enum conversion", () => tObject.MyEnumFieldValue = (TestEnum)0, () => iObj.MyEnumFieldValue = 0); Runner.RunF("Get Public Field. Float->Object conversion", () => (object)tObject.FieldNumber, () => iObj.FieldNumberObject); Runner.RunA("Set Public Field. Object(Float)->Float conversion", () => tObject.FieldNumber = (float)(object)51f, () => iObj.FieldNumberObject = 51f); Runner.RunA("Set Public Field. Object(Int)->Float conversion", () => tObject.FieldNumber = (float)Convert.ChangeType(42, typeof(float)), () => iObj.FieldNumberObject = 42); } }
public static object DuckCast(this object instance, Type targetType) => DuckType.Create(targetType, instance);
public static T DuckCast <T>(this object instance) => DuckType.Create <T>(instance);
public static object DuckAs(this object instance, Type interfaceType) => DuckType.Create(interfaceType, instance);
public static T DuckAs <T>(this object instance) where T : class => DuckType.Create <T>(instance);