Appearance
动态代理
动态代理是AsDI的整个项目的基础。动态代理属于软件开发模式中的代理模式。我们可以通过动态代理,来动态实现我们的各种抽象类或接口。
注意
非特殊情况,请选择使用切面即可,不需要使用动态代理,切面也是通过动态代理实现的
AsDI的动态代理需要定义一个代理类继承自 IDynamicProxy 或 DynamicProxyBase , 并定义它的 [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"}]