I am having trouble getting Castle Dynamic Proxy to intercept methods that are explicit interface implementations. I read here http://kozmic.pl/category/dynamicproxy/ that it should be possible to do this.
Here are my classes;
internal interface IDomainInterface
{
string DomainMethod();
}
public class DomainClass : IDomainInterface
{
string IDomainInterface.DomainMethod()
{
return "not intercepted";
}
}
Here is my interceptor class;
public class DomainClassInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name == "DomainMethod")
invocation.ReturnValue = "intercepted";
else
invocation.Proceed();
}
}
And here is my test (which fails);
[TestClass]
public void can_intercept_explicit_interface_implementation()
{
// Create proxy
var generator = new ProxyGenerator();
var interceptor = new DomainClassInterceptor();
var proxy = (IDomainInterface)generator.CreateClassProxy(typeof(DomainClass), interceptor);
// Invoke proxy method
var result = proxy.DomainMethod();
// Check method was intercepted -- fails
Assert.AreEqual("intercepted", result);
}
In addition to not being able to intercept the explicit interface implementation, it also seems that I am not receiving a notification of a non-proxyable member.
Here is my proxy generation hook (which acts as a spy);
public class DomainClassProxyGenerationHook : IProxyGenerationHook
{
public int NonProxyableCount;
public void MethodsInspected() {}
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo)
{
NonProxyableCount++;
}
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
return true;
}
}
Here is my test (which again fails);
[TestMethod]
public void receive_notification_of_nonproxyable_explicit_interface_implementation()
{
// Create proxy with generation hook
var hook = new DomainClassProxyGenerationHook();
var options = new ProxyGenerationOptions(hook);
var generator = new ProxyGenerator();
var interceptor = new DomainClassInterceptor();
var proxy = (IDomainInterface)generator.CreateClassProxy(typeof(DomainClass), options, interceptor);
// Check that non-proxyable member notification was received -- fails
Assert.IsTrue(hook.NonProxyableCount > 0);
}
Has anyone had success in getting DP to intercept explicit interface implementations? If so, how?
You are creating a class proxy. Class proxy only intercepts virtual methods on the class, and an explicit implementation of an interface method in C# by definition is not virtual (since it's private).
If you want to intercept methods on the interface you need to explicitly tell DynamicProxy about it
var proxy = (IDomainInterface)generator.CreateClassProxy(typeof(DomainClass), new Type[] { typeof(IDomainInterface) }, interceptor);
Also your interface is marked as internal so made sure it's public for DynamicProxy (either make the interface public or add InternalsVisibleToAttribute).
With that your first test will pass, and the method will be intercepted.
Related
I'm using MySQL with EF Core. I am currently using Pomelo Provider for MySQL. I need to implement Unit Of Work Pattern for transactions. I have a Service which calls two methods in repository. I am not able to implement nested transactions. This is how my method in service looks now:
public void methodA(param)
{
using (TransactionScope tx = new
TransactionScope(TransactionScopeOption.Required))
{
repo1.save(data1);
repo2.save(data2);
tx.complete();
}
}
This is how save method in repo1 is implemented
private readonly UserDbContext appDbContext;
public repo1(UserDbContext _appDbContext)
{
appDbContext = _appDbContext;
}
public void save(User entity)
{
var dbset = appDbContext.Set<User>().Add(entity);
appDbContext.SaveChanges();
}
This is how save method in repo2 is implemented
private readonly UserDbContext appDbContext;
public repo2(UserDbContext _appDbContext)
{
appDbContext = _appDbContext;
}
public void save(UserRole entity)
{
var dbset = appDbContext.Set<UserRole>().Add(entity);
appDbContext.SaveChanges();
}
I am getting the following error while running method in service:
Error generated for warning 'Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning: An ambient transaction has been detected. The current provider does not support ambient transactions. See http://go.microsoft.com/fwlink/?LinkId=800142'. This exception can be suppressed or logged by passing event ID 'RelationalEventId.AmbientTransactionWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
This is how I registered UserDbContext in Startup.cs
services.AddDbContext<UserDbContext>(options => options.UseLazyLoadingProxies().UseMySql("Server = xxxx; Database = xxx; Uid = xx;ConnectionReset=True;", b => b.MigrationsAssembly("AssemblyName")));
I even tried adding a middleware which starts transaction at the begining of request and commits/rollbacks during the response . But still I am not able to manage nested transactions.
This is how my middleware looks:
public class TransactionPerRequestMiddleware
{
private readonly RequestDelegate next_;
public TransactionPerRequestMiddleware(RequestDelegate next)
{
next_ = next;
}
public async Task Invoke(HttpContext context, UserDbContext
userDbContext)
{
var transaction = userDbContext.Database.BeginTransaction(
System.Data.IsolationLevel.ReadCommitted);
await next_.Invoke(context);
int statusCode = context.Response.StatusCode;
if (statusCode == 200 || statusCode==302)
{
transaction.Commit();
}
else
{
transaction.Rollback();
}
}
}
Can anyone help me please?
I will insert logs from exception handler and i've action for post logs. How can I call my service action properly?
Is creating instance everytime correct?
public class CustomExceptionHandler : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exceptionModel = new System_Logs() { Date = DateTime.Now, Request = actionExecutedContext.Request.RequestUri.AbsoluteUri, Response = actionExecutedContext.Response.Content.ToString()};
System_LogsController controller = new System_LogsController();
controller.PostSystem_Logs(exceptionModel);
base.OnException(actionExecutedContext);
}
}
You should create a logging service class (not a controller class) that will handle logging. If you are using dependency injection, for custom filter attributes use property injection using the [Dependency] annotation/decorator to the property. This logging service will be initialized via injection container. You can search in SO for IoC (e.g Unity, autofac, ninject, etc) to help you get started. It's worth knowing this IoC and dependency injection principles as it can apply both on the server side and in the client side(javascript development).
To elaborate on what you currently have. Your code above will look like something like:
public class CustomExceptionHandler : ExceptionFilterAttribute
{
[Dependency]
public ILoggingService LoggingService { get; set; }
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exceptionModel = new System_Logs() { Date = DateTime.Now, Request = actionExecutedContext.Request.RequestUri.AbsoluteUri, Response = actionExecutedContext.Response.Content.ToString()};
LoggingService.PostSystemLogs(exceptionModel);
base.OnException(actionExecutedContext);
}
}
Although I'm relatively new to AutoMapper I'm using it in a small project I'm developing. I've never had problems using it before but now I'm facing some weird behavior passing parameters to a Custom Resolver.
Here's the scenario: I get a list of messages from my repository and then map those to a frontend friendly version of it. Nothing fancy, just some normal mapping between objects. I have a field in that frontend object that tells if a certain user already voted for that message and that's what I'm using the Custom Resolver for (it's that second "ForMember"):
public List<SupportMessageUi> GetAllVisible(string userId)
{
Mapper.CreateMap<SupportMessage, SupportMessageUi>()
.ForMember(dest => dest.Votes,
opt => opt.ResolveUsing<SupportMessageVotesResolver>())
.ForMember(dest => dest.UserVoted,
opt => opt.ResolveUsing<SupportMessagesUserVotedResolver>()
.ConstructedBy(() => new SupportMessagesUserVotedResolver(userId)));
var messages = _unitOfWork.MessagesRepository.Get(m => m.Visible);
var messagesUi = Mapper.Map<List<SupportMessageUi>>(messages);
return messagesUi;
}
I'm calling this method on a web service and the problem is: the first time I call the webservice (using the webservice console) it all runs perfectly. For example, if I pass '555' as the userId I get to this method with the correct value:
And in the Custom Resolver the value was correctly passed to the constructor:
The results returned are correct. The problem comes next. The second time I call the service, passing a different argument ('666' this time) the argument that gets to the constructor of the Custom Resolver is the old one ('555'). Here's what I mean:
Right before mapping the objects we can see that the value passed to the constructor was correct ('666'):
But when it gets to the constructor of the Resolver the value is wrong, and is the old one ('555'):
All subsequent calls to the service use the original value in the Custom Resolver constructor ('555'), independently of the value I pass to the service (also happens if I make the call from another browser). If I shut down the server and relaunch it I can pass a new parameter (that will be used in all other calls until I shut it down again).
Any idea on why this is happening?
It's happening because AutoMapper.CreateMap is a static method, and only needs to be called once. With the CreateMap code in your web method, you're trying to call it every time you call that method on your web service. Since the web server process stays alive between calls (unless you restart it, like you said) then the static mappings stay in place. Hence, the necessity of calling AutoMapper.Reset, as you said in your answer.
But it's recommended that you put your mapping creation in AppStart or Global or a static constructor or whatever, so you only call it once. There are ways to call Map that allow you to pass in values, so you don't need to try to finesse things with the constructor of your ValueResolver.
Here's an example using a ValueResolver (note the change to implementing IValueResolver instead of inheriting ValueResolver<TSource, TDestination>):
[Test]
public void ValueTranslator_ExtraMapParameters()
{
const int multiplier = 2;
ValueTranslator translator = new ValueTranslator();
Mapper.AssertConfigurationIsValid();
ValueSource source = new ValueSource { Value = 4 };
ValueDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(8));
source = new ValueSource { Value = 5 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(10));
}
private class ValueTranslator
{
static ValueTranslator()
{
Mapper.CreateMap<ValueSource, ValueDest>()
.ForMember(dest => dest.Value, opt => opt.ResolveUsing<ValueResolver>().FromMember(src => src.Value));
}
public ValueDest Translate(ValueSource source, int multiplier)
{
return Mapper.Map<ValueDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class ValueResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
return source.New((int)source.Value * (int)source.Context.Options.Items["multiplier"]);
}
}
}
private class ValueSource { public int Value { get; set; } }
private class ValueDest { public int Value { get; set; } }
And here's an example using a TypeConverter:
[Test]
public void TypeTranslator_ExtraMapParameters()
{
const int multiplier = 3;
TypeTranslator translator = new TypeTranslator();
Mapper.AssertConfigurationIsValid();
TypeSource source = new TypeSource { Value = 10 };
TypeDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(30));
source = new TypeSource { Value = 15 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(45));
}
private class TypeTranslator
{
static TypeTranslator()
{
Mapper.CreateMap<TypeSource, TypeDest>()
.ConvertUsing<TypeConverter>();
}
public TypeDest Translate(TypeSource source, int multiplier)
{
return Mapper.Map<TypeDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class TypeConverter : ITypeConverter<TypeSource, TypeDest>
{
public TypeDest Convert(ResolutionContext context)
{
TypeSource source = (TypeSource)context.SourceValue;
int multiplier = (int)context.Options.Items["multiplier"];
return new TypeDest { Value = source.Value * multiplier };
}
}
}
private class TypeSource { public int Value { get; set; } }
private class TypeDest { public int Value { get; set; } }
Answering myself: I was not using AutoMapper.Reset(). Once I did that everything started working properly.
Helpful reading: http://www.markhneedham.com/blog/2010/01/27/automapper-dont-forget-mapper-reset-at-the-start/
I'm using Windsor to manage IoC for my controllers in a WebAPI project. I've got a DependencyResolver working nicely to resolve controller dependencies, but now I'm looking to inject dependencies into a custom action filter I'm using to manage authentication.
I've looked into using a custom ActionInvoker but it's not clear from the interface that WebAPI is using how I would go about resolving property dependencies on the custom action filter attribute before it executes. Anyone have a good example of how to do this in the MVC 4 RC?
EDIT: I'm aware you can't do constructor injection on filters, because they're attributes and therefore instantiated by the .NET framework - but I'm hoping there's some point in the execution lifecycle that happens AFTER the filter is instantiated but BEFORE it gets executed, where I could run some custom code to enumerate across the filters' public properties and inject the necessary services.
Action filters are attributes. In .NET attribute the instantiation process is managed by the .NET runtime and you don't have control over it. So one possibility is to use Poor Man's Dependency Injection which I would personally advice you against.
Another possibility is to use a marker attribute:
public class MyActionFilterAttribute : Attribute
{
}
and then have the action filter using constructor injection:
public class MyActionFilter : ActionFilterAttribute
{
private readonly IFoo _foo;
public MyActionFilter(IFoo foo)
{
_foo = foo;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ActionDescriptor.GetCustomAttributes<MyActionFilterAttribute>().Any())
{
// The action is decorated with the marker attribute =>
// do something with _foo
}
}
}
and then register it as a global action filter in Application_Start:
IFoo foo = ....
GlobalConfiguration.Configuration.Filters.Add(new MyActionFilter(foo));
I had the same problem, but decided to go for the ServiceLocator (DependencyResolver.GetService) for this, as its in the framework it seems to me to be a valid approach
public class RequiresSessionAttribute :
ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var sessionService =
(ISessionService) actionContext
.ControllerContext.Configuration.DependencyResolver
.GetService(typeof (ISessionService));
var sessionId = HttpUtility
.ParseQueryString(actionContext.Request.RequestUri.Query)
.Get("sessionId");
if (sessionId == null
|| !sessionService.IsValid(sessionId))
throw new SessionException();
base.OnActionExecuting(actionContext);
}
}
and here is a test for this attribute, bit of a pain but possible
public class requires_sessionId
{
[Fact]
void can_call_action_with_session_id()
{
var context = GetContext("http://example.com/?sessionId=blaa");
var sut = new RequiresSessionAttribute();
Assert.DoesNotThrow(
() => sut.OnActionExecuting(context));
}
[Fact]
void can_not_call_action_without_session_id()
{
var context = GetContext("http://example.com/");
var sut = new RequiresSessionAttribute();
Assert.Throws<SessionException>(
() => sut.OnActionExecuting(context));
}
HttpActionContext GetContext(string url)
{
var sessionServiceMock = new Mock<ISessionService>();
sessionServiceMock
.Setup(x => x.IsValid(It.IsAny<string>()))
.Returns(true);
var dependancyResolverMock = new Mock<IDependencyResolver>();
dependancyResolverMock
.Setup(x => x.GetService(It.IsAny<Type>()))
.Returns(sessionServiceMock.Object);
var config = new HttpConfiguration
{
DependencyResolver = dependancyResolverMock.Object
};
var controllerContext = new HttpControllerContext
{
Configuration = config,
Request = new HttpRequestMessage(
HttpMethod.Get,
url)
};
return
new HttpActionContext
{
ControllerContext = controllerContext,
};
}
}
My colleague set up a Windsor TypedFactoryFacility in our project.
I'm new to Windsor and don't understand how it is implementing the the methods in the IServiceFactory interface we register as a factory. When I saw a Create method that takes a type parameter T and returns a T, I figured that it's probably calling the container's Resolve method under the covers.
I need an overload of Create that takes a Type as a parameter and returns an object. Since the container's Resolve method has both of these flavors:
T Resolve<T>(string key);
object Resolve(Type service);
I thought adding the overload of Create would work. Instead, it appears to be trying to resolve a System.Object instead of the Type I pass in.
Is there a way to make Windsor implement my Create method the way I want it to? I've poked around a bit with reflector, but can't figure it out.
Here is the registration:
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IServiceFactory>()
.AsFactory()
.LifeStyle.Transient);
and the interface itself:
public interface IServiceFactory
{
//Original Create method that works
T Create<T>();
//The overload that I need that throws an exception
object Create(Type service)
void Release(object service);
}
Do you want to call something like serviceFactory.Create(typeof(IMyServce)) instead of serviceFactory.Create<IMyService>()?
Try using reflection in an extension method, like this
public static class ServiceFactoryExtensions
{
public static object Create(this IServiceFactory factory, Type serviceType)
{
return typeof(IServiceFactory).GetMethod("Create")
.MakeGenericMethod(serviceType).Invoke(factory, new object[]{});
}
}
EDIT:
This extension method does indeed work with a factory created by Castle Windsor.
Here's my original test code, which you can drop into Program.cs of a VS2010 console application, add a reference to Castle.Core and Castle.Windsor, and run. I used Castle.Windsor 2.5.4.
using System;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace StackOverflow9198461
{
public static class ServiceFactoryExtensions
{
public static object Create(this IServiceFactory factory, Type serviceType)
{
return typeof(IServiceFactory).GetMethod("Create")
.MakeGenericMethod(serviceType)
.Invoke(factory, new object[] { });
}
}
class Program
{
static void Main()
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component
.For<IServiceFactory>()
.AsFactory());
container.Register(Component
.For<IMyService>()
.ImplementedBy<MyService>()
.LifeStyle.Singleton);
var factory = container.Resolve<IServiceFactory>();
var s1 = factory.Create<IMyService>();
var s2 = factory.Create(typeof(IMyService));
Console.WriteLine(s1.GetType().FullName);
Console.WriteLine(s2.GetType().FullName);
if (s1 == s2) Console.WriteLine("Success");
}
}
public interface IServiceFactory
{
//Original Create method that works
T Create<T>();
////The overload that I need that throws an exception
//object Create(Type service)
void Release(object service);
}
public class MyService : IMyService
{
}
public interface IMyService
{
}
}