惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
V
V2EX
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
爱范儿
爱范儿
Jina AI
Jina AI
博客园 - Franky
IT之家
IT之家
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
The Cloudflare Blog
M
MIT News - Artificial intelligence
aimingoo的专栏
aimingoo的专栏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
人人都是产品经理
人人都是产品经理
腾讯CDC
博客园_首页
月光博客
月光博客
有赞技术团队
有赞技术团队
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog

博客园 - 芭蕉

Model-View-ViewModel(MVVM) with MEF 使用EnvDTE自动格式整个工程 Inversion of Control Dynamic Proxy C# 4.0 Dynamic --通过DLR直接调用IronPython 介绍一个Python进行函数式编程时有用的module - 芭蕉 - 博客园 lambda in F# - 芭蕉 UML类关系图标识速记 Python functions VisualStudio quick tips -- 快速在多个打开的代码文件间切换 VisualStudio quick tips --快速调整字体大小 结合实例实习F#(三)--理解函数式语言中的函数 VisualStudio quick tips --快速打开Properties Page 结合实例学习F#(二) --基本数据类型Discriminated Unions 结合实例学习F#(一) --快速入门 Failed to generate a user instance of SQL Server due to a failure in starting the process for the user instance Factory Method 顺时钟方向螺旋状打印矩阵元素 玩转Visual Studio ---Debug篇
Duck Typing in C# - 芭蕉
芭蕉 · 2010-01-05 · via 博客园 - 芭蕉

"when I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck" -- James Whitcomb Riley

It's really easy to implement duck typing in C# 4.0 since it introduced dynamic into its toolsets. The following is just some scratch to help me familiar with the dynamic feature (plus dynamic proxy from castle project )

代码

using System.Collections.Generic;
using System.Dynamic;
using System.Linq;namespace DynamicDuckTypeing
{
    
class DynamicWrapper : DynamicObject
    {
        
object _obj;
        Dictionary
<stringobject> _dictionary = new Dictionary<stringobject>();public DynamicWrapper(object obj)
        {
            _obj 
= obj;
        }
public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            
return TrySetMember(binder.Name, value);
        }
internal virtual bool TrySetMember(string name, object value)
        {
            var memberInfo 
= _obj.GetType().GetMember(name);
            
if (memberInfo.Count() == 0)
            {
                _dictionary[name] 
= value;
            }
            
else
            {
                _obj.GetType().InvokeMember(name,
                    System.Reflection.BindingFlags.SetProperty,
                    
null,
                    _obj,
                    
new object[] { value });
            }
            
return true;
        }
internal virtual bool TryGetMember(string name, out object result)
        {
            var memberInfo 
= _obj.GetType().GetMember(name);
            
if (memberInfo.Count() == 0)
            {
                
return _dictionary.TryGetValue(name, out result);
            }
            
else
            {
bool invokeSucceed = true;
                
try
                {
                    result 
= _obj.GetType().InvokeMember(name,
                        System.Reflection.BindingFlags.GetProperty,
                        
null,
                        _obj,
                        
null);
                }
                
catch
                {
                    result 
= null;
                    invokeSucceed 
= false;
                }
                
return invokeSucceed;
            }
        }
        
public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            
return TryGetMember(binder.Name,out result);
            
        }
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            
return TryInvokeMember(binder.Name, args, out result);
        }
internal bool TryInvokeMember(string memberName, object[] args, out object result)
        {
            _obj.GetType().InvokeMember(memberName,
              System.Reflection.BindingFlags.InvokeMethod,
              
null,
              _obj, args);
            result 
= null;
            
return true;
        }
public override bool TryConvert (ConvertBinder binder, out object result)
        {          
            result 
= Generator.GenerateProxy(binder.Type,this);
            
return true;
        }
    }
}

代码

using System;
using Castle.DynamicProxy;
using Castle.Core.Interceptor;namespace DynamicDuckTypeing
{
    
class Generator
    {
        
static readonly ProxyGenerator _generator = new ProxyGenerator();       internal static object GenerateProxy(Type type, DynamicWrapper dynamicWrapper)
        {
            
return _generator.CreateInterfaceProxyWithoutTarget(type, new Interceptor(dynamicWrapper));
        }
    }
class Interceptor : IInterceptor
    {
        DynamicWrapper _wrapper;
        
public Interceptor(DynamicWrapper wrapper)
        {
            _wrapper 
= wrapper;
        }
        
public void Intercept(IInvocation invocation)
        {
            
            
object result;//property access will be converted to get_XXX and set_XXX, use String.Substring(4) to get the real proertyName
            if (invocation.Method.Name.StartsWith("get_"))
            {
                invocation.ReturnValue 
= _wrapper.TryGetMember(invocation.Method.Name.Substring(4), out result);
                invocation.ReturnValue 
= result;
            }
            
else if (invocation.Method.Name.StartsWith("set_"))
            {
                _wrapper.TrySetMember(invocation.Method.Name.Substring(
4), invocation.Arguments[0]);
            }
            
else
            {
                _wrapper.TryInvokeMember(invocation.Method.Name, invocation.Arguments, 
out result);
                invocation.ReturnValue 
= result;
            }
        }
    }
}

代码

using System;namespace DynamicDuckTypeing
{
    
public interface IQuack
    {
        
void Quack();   
    }
class Duck
    {        
        
public void Quack()
        {
            Console.WriteLine(
"Duck Quack");
        }
    }
class Goose
    {
        
public void Quack()
        {
            Console.WriteLine(
"Goose goose");
        }
    }
    
class Program
    {
        
static void Main(string[] args)
        { 
            dynamic dynamicDuck 
= new DynamicWrapper( new Duck());            
            dynamicDuck.Name 
= "mallard duck";           
            dynamicDuck.Age 
= 2;
            Console.WriteLine(
"Name: {0}, Age: {1}",dynamicDuck.Name, dynamicDuck.Age);
            dynamicDuck.Quack();
            Console.WriteLine();
                        
            IQuack q 
= dynamicDuck;            
            q.Quack();

            dynamic dynamicGoose 

= new DynamicWrapper(new Goose());
            q 
= dynamicGoose;
            q.Quack();

            q 

= (dynamic)new DynamicWrapper(new object());
            
try
            {
                q.Quack();
                Console.WriteLine(
"can't be there");
            }
            
catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }
}