我有一个类,我用Castle Dynamic Proxy代理它。我想为代理方法添加一些自定义属性(在代理类中没有定义)。这可能。
我想要这个,因为我想为我的应用程序的服务层生成ASP.NET Web API层。我代理服务(继承自ApiController和其他IMyService接口),它工作得很好,但我想为这个新创建的Dynamic类添加特定于WebAPI的属性,因此Web API框架可以读取它们。
修改:
如果有人想知道我想要的东西,我想详细解释。
public interface IMyService
{
IEnumerable<MyEntity> GetAll();
}
public class MyServiceImpl : IMyService
{
public IEnumerable<MyEntity> GetAll()
{
return new List<MyEntity>(); //TODO: Get from database!
}
}
public class MyServiceApiController : ApiController,IMyService
{
private readonly IMyService _myService;
public MyServiceApiController(IMyService myService)
{
_myService = myService;
}
public IEnumerable<MyEntity> GetAll()
{
return _myService.GetAll();
}
}
认为我有一个由MyServiceImpl实现的IMyService。我想让一个Api控制器能够从网上使用这项服务。 但正如您所见,api控制器只是实际服务的代理。那么,为什么我要写呢?我可以使用城堡windsor动态创建它。
这是我的想法,几乎在我的新项目(https://github.com/hikalkan/aspnetboilerplate)中完成。但是,如果我需要向api控制器的GetAll方法添加一些属性(例如Authorize),该怎么办呢?我不能直接添加,因为没有这样的类,它是城堡动态代理。
所以,除了这个问题。我想知道是否可以将属性添加到synamic代理类的方法中。
答案 0 :(得分:2)
再次看到那个项目 https://github.com/aspnetboilerplate/aspnetboilerplate/issues/55 我也想知道如何,以便我可以在IService和Route on Action上定义RoutePrefix。 幸运的是,我终于知道如何为代理定义自定义属性。
public class CustomProxyFactory : DefaultProxyFactory
{
#region Overrides of DefaultProxyFactory
protected override void CustomizeOptions(ProxyGenerationOptions options, IKernel kernel, ComponentModel model, object[] arguments)
{
var attributeBuilder = new CustomAttributeBuilder(typeof(DescriptionAttribute).GetConstructor(new[] { typeof(string) }), new object[] { "CustomizeOptions" });
options.AdditionalAttributes.Add(attributeBuilder);
}
#endregion
}
/// <summary>
/// 用户信息服务
/// </summary>
[Description("IUserInfoService")]
public interface IUserInfoService
{
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[Description("IUserInfoService.GetUserInfo")]
UserInfo GetUserInfo([Description("IUserInfoService.GetUserInfo name")] string name);
}
/// <summary>
/// 用户信息服务
/// </summary>
[Description("UserInfoService")]
public class UserInfoService : IUserInfoService
{
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
[Description("UserInfoService.GetUserInfo")]
public virtual UserInfo GetUserInfo([Description("UserInfoService.GetUserInfo name")] string name)
{
return new UserInfo { Name = name };
}
}
using DescriptionAttribute = System.ComponentModel.DescriptionAttribute;
[TestFixture]
public class AttributeTests
{
/// <summary>
/// Reference to the Castle Windsor Container.
/// </summary>
public IWindsorContainer IocContainer { get; private set; }
[SetUp]
public void Initialize()
{
IocContainer = new WindsorContainer();
IocContainer.Kernel.ProxyFactory = new CustomProxyFactory();
IocContainer.Register(
Component.For<UserInfoService>()
.Proxy
.AdditionalInterfaces(typeof(IUserInfoService))
.LifestyleTransient()
);
}
/// <summary>
///
/// </summary>
[Test]
public void GetAttributeTest()
{
var userInfoService = IocContainer.Resolve<UserInfoService>();
Assert.IsNotNull(userInfoService);
var type = userInfoService.GetType();
Assert.IsTrue(type != typeof(UserInfoService));
var attribute = type.GetCustomAttribute<DescriptionAttribute>();
Assert.IsTrue(attribute != null);
Trace.WriteLine(attribute.Description);
var method = type.GetMethod("GetUserInfo");
attribute = method.GetCustomAttribute<DescriptionAttribute>();
Assert.IsTrue(attribute != null);
Trace.WriteLine(attribute.Description);
var parameter = method.GetParameters().First();
attribute = parameter.GetCustomAttribute<DescriptionAttribute>();
Assert.IsTrue(attribute != null);
Trace.WriteLine(attribute.Description);
}
}
答案 1 :(得分:0)
@hikalkan我遇到了同样的问题,我也在寻找解决方案。我遇到的最好的是 How to add an attribute to a property at runtime
使用新的包装器代理控制器(在我的情况下是动态控制器),该包装器在类本身及其方法中设置这些属性。