Skip to content

动态代理

动态代理是AsDI的整个项目的基础。动态代理属于软件开发模式中的代理模式。我们可以通过动态代理,来动态实现我们的各种抽象类或接口。

注意

非特殊情况,请选择使用切面即可,不需要使用动态代理,切面也是通过动态代理实现的

AsDI的动态代理需要定义一个代理类继承自 IDynamicProxyDynamicProxyBase , 并定义它的 [Fit] 标注规定其作用范围

示例1 - 动态参数自动注入

下面的示例, 用于所有方法的参数自动注入:

C#
[Fit("1")]
public class AutoInjectProxy : DynamicProxyBase
{
    public override object Invoke(object target, ProxyMethod method)
    {
        foreach (var arg in method.Arguments)
        {
            if (arg.Value == null)
            {
                var attr = arg.Parameter.GetCustomAttribute<AutoAssembleAttribute>();
                if (attr != null)
                {
                    var value = AsDIContext.Get(arg.Type, attr.Version ?? -1);
                    arg.Value = value;
                }
            }
        }

        return base.Invoke(target, method);
    }
}

上面的动态代理,用于当传入参数中,参数值为null且参数含有 [AutoAssemble] 标注,那么动态代理会协助动态传入需要的参数,使用如下:

C#
public interface IUserController
{
    public void Print([AutoAssemble] IUserService user = null);
}

[Service]
public class UserController : IUserController
{
    public void Print([AutoAssemble] IUserService user = null)
    {
        Console.WriteLine("Hello " + user.GetUserName());
    }
}

public interface IUserService
{
    string GetUserName();
}

[Service(1)]
public class UserService1 : IUserService
{
    public string GetUserName()
    {
        return "Jack";
    }
}

[Include]
public class Program
{
    [AutoAssemble]
    private static IUserController controller;

    static void Main(string[] args)
    {
        AsDIContext.Start();
        controller.Print();
    }

}

此时,在调用Controller时,并不需要传入参数,参数会自动注入到这个方法的实际调用中。以上输出结果:

sh
> Hello Jack

示例2 - 无需定义实现类

下面的示例,用于数据库(Sql Server)自动读取数据,并将返回数据:

C#
[Fit("name('.*Dao')")]
public class DataBaseProxy : IDynamicProxy
{
    public object Invoke(object target, ProxyMethod method)
    {
        string tableName = method.TypeName.Substring(0, method.TypeName.LastIndexOf("Dao"));
        StringBuilder sql = new StringBuilder("select * from [" + tableName + "] where 1=1 and ");
        Dictionary<string, object> queryParams = new Dictionary<string, object>();
        foreach (var arg in method.Arguments)
        {
            sql.Append(" and [" + arg.Name + "]=@" + arg.Name);
            queryParams.Add(arg.Name, arg.Value);
        }

        return DbHelper.Query(method.ReturnType, sql.ToString(), queryParams);

    }
}

此时只需要定义接口即可,不需要去实现接口,如下:

C#
public class User
{
    public string Name { get; set; }
    public string Id { get; set; }
    public string Email { get; set; }
}

[Include]
public interface UserDao
{
    List<User> QueryByName(string name);
}

[Include]
public class Program
{
    [AutoAssemble]
    private static UserDao dao;

    static void Main(string[] args)
    {
        AsDIContext.Start();
        List<User> result = dao.QueryByName("Jack");
        Console.WriteLine("查询成功,返回结果:{0}", JsonConvert.SerializeObject(result));
    }
}

此时,动态代理会调用数据库并查询,获取查询结果。以上输出结果:

sh
> 查询成功,返回结果:[{"Name":"Jack","Id":"001","Email":"Jack@xxx.com"}]

沪ICP备2025119739号