Autofac Performance Tuning - autofac

We have implmeneted the following Autofac code using SingleInstance in c# code. We found its taking time around 3 to 4 seconds for intiating the constructors for all the services for every time when we call the particular services.
Please find below the following code implementation.
private static void RegisterDependency(HttpConfiguration config)
{
Log.Trace("Registering dependencies");
var builder = new ContainerBuilder();
HttpContextBase httpContextBase = new HttpContextWrapper(HttpContext.Current);
var configService = new ConfigurationService(httpContextBase, new CacheWrapper());
var stubModeValue = configService.GetResourcePreferenceValueByKeyName("stubMode", "N");
var isStubMode = "Y".Equals(stubModeValue, StringComparison.OrdinalIgnoreCase);
builder.RegisterAssemblyTypes(typeof(ClientService).Assembly).Where(x => x.isClass && x.isPublic && !x.isAbstract)
.Where(x => isStubMode = x.Name.EndsWith("stub").AsImplementedInterface();
RegisterServiceProxy<ExternalService1>(builder);
RegisterServiceProxy<ExternalService2>(builder);
RegisterServiceProxy<ExternalService3>(builder);
builder.Register<IUserProfile>(x => OwnerIdentityAndRoleProfile.Current).InstancePerLifeTimeScope();
builder.Register<IConfigurationService>(c => new ConfigurationService(httpContextBase, new CacheWrapper()).InstancePerLifeTimeScope;
builder.RegisterType<ServiceProxyProvider>().SingleInstance();
builder.RegisterType<wsProfileWrapper>() As <wsProfileWrapper>();
var container = builder.build();
ServiceProxyProvider = container.Resolve<serviceProxyProvider>();
config.DependencyResolver = new AutofacWebAPIDependencyResolver(container);
Log.Trace("Completed Registering dependencies");
}
static void RegisterServiceProxy<T> (ContainerBuilder builder) where T:class
{
builder.Register(_ => _serviceProxyProvider.CreateServiceProxyInstance<T>()).InstancePerRequest()
.OnRelease(x => _serviceProxyProvider.Dispose(x));
}
Thanks.

Related

How can I get constructor parameters of autofac component on activating

What I want is create caching proxies for all my components decorated with some attributes. So, I made Autofac Module like this:
public class CachingModule : Autofac.Module
{
private readonly ProxyGenerator generator;
public CachingModule()
{
generator = new ProxyGenerator();
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
var type = registration.Activator.LimitType;
if (type.GetCustomAttribute<CachedAttribute>(true) != null
|| type.GetMethods().Any(m => m.GetCustomAttribute<CachedAttribute>(true) != null))
{
registration.Activating += (s, e) =>
{
var proxy = generator.CreateClassProxyWithTarget(e.Instance.GetType(),
e.Instance,
interceptors: e.Context.Resolve<IEnumerable<CacheInterceptor>>().ToArray());
e.ReplaceInstance(proxy);
};
}
}
}
What I can't get to work is: I can't create proxy instances with parametrized constructors, is there any way to do this?
Ok, I've managed to get it all working, so for anyone interested here is a sample of proxy generation with non-default constructors
public class CachingModule : Autofac.Module
{
private readonly ProxyGenerator generator;
public CachingModule()
{
generator = new ProxyGenerator();
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
var type = registration.Activator.LimitType;
if (type.GetCustomAttribute<CachedAttribute>(true) != null
|| type.GetMethods().Any(m => m.GetCustomAttribute<CachedAttribute>(true) != null))
{
var ctors = type.GetConstructors();
registration.Activating += (s, e) =>
{
if (e.Instance is IProxyTargetAccessor)
{
return;
}
var param = new List<object>();
var infos = ctors.First().GetParameters();
if (ctors.Length > 0 && infos.Length > 0)
{
foreach (var p in e.Parameters)
{
foreach (var info in infos)
{
if (p.CanSupplyValue(info, e.Context, out var valueProvider))
{
param.Add(valueProvider());
}
}
}
}
var instance = e.Instance;
var toProxy = instance.GetType();
var proxyGenerationOptions = new ProxyGenerationOptions(new CacheProxyGenerationHook());
var proxy = generator.CreateClassProxyWithTarget(toProxy,
instance,
proxyGenerationOptions,
param.ToArray(),
interceptors: e.Context.Resolve<IEnumerable<CacheInterceptor>>().ToArray());
e.ReplaceInstance(proxy);
};
}
}
}

How to avoid disposing SubscriberSocket

This implementation is bad since it will end up disposing the SubscriberSocket when the first subscription terminates. When I run it, nothing seems to publish. [This uses Rx 3.0.0]
How to modify Receive function to fix this problem?
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using NetMQ;
using NetMQ.Sockets;
using System.Reactive.Linq;
namespace App1
{
class MainClass
{
// publisher for testing, should be an external data publisher in real environment
public static Thread StartPublisher(PublisherSocket s)
{
s.Bind("inproc://test");
var thr = new Thread(() =>
{
Console.WriteLine("Start publishing...");
while (true)
{
Thread.Sleep(500);
bool more = false;
s.SendFrame("hello", more);
}
});
thr.Start();
return thr;
}
public static IObservable<string> Receive(SubscriberSocket subp)
{
return Observable
.Create<string>(o =>
Observable.Using<string, SubscriberSocket>(() =>
{
subp.Connect("inproc://test");
subp.Subscribe("");
return subp;
}, sub =>
Observable
.FromEventPattern<EventHandler<NetMQSocketEventArgs>, NetMQSocketEventArgs>(
h => sub.ReceiveReady += h,
h => sub.ReceiveReady -= h)
.Select(x => sub.ReceiveFrameString()))
.Subscribe(o));
}
public static void Main(string[] args)
{
var sub = new SubscriberSocket();
var pub = new PublisherSocket();
StartPublisher(pub);
Receive(sub).Subscribe(Console.WriteLine);
Console.ReadLine();
}
}
}
It seems to me that you should be doing something like this:
void Main()
{
var address = "inproc://test";
var pub = new PublisherSocket();
pub.Bind(address);
var pubSubscription =
Observable
.Interval(TimeSpan.FromMilliseconds(500.0))
.Subscribe(n => pub.SendFrame("hello", false));
Receive(address).Subscribe(Console.WriteLine);
Console.ReadLine();
}
public static IObservable<string> Receive(string address)
{
return Observable
.Create<string>(o =>
Observable.Using<string, SubscriberSocket>(() =>
{
var ss = new SubscriberSocket();
ss.Connect(address);
ss.Subscribe("");
return ss;
}, ss =>
Observable
.FromEventPattern<EventHandler<NetMQSocketEventArgs>, NetMQSocketEventArgs>(
h => ss.ReceiveReady += h,
h => ss.ReceiveReady -= h)
.Select(x => ss.ReceiveFrameString()))
.Subscribe(o));
}
Primarily, this means creating the SubscriberSocket inside the Observable.Create - which is where it belongs.

Hangfire , EF context used in the Task is not updated, the query inside the task always gives the old values

The context used inside the Hangfire task , always gives the old database values, it seems like the context is not updating inside the task. How to get the updated info context data inside hangfire task.
calling the task
BLL.Extraction NewExtractionCls = new BLL.Extraction();
var jobId = BackgroundJob.Enqueue(() => NewExtractionCls.SearchEngineExtraction("SearchURL", "1","1", null));
This is implementation
[Authorize]
public void SearchEngineExtraction(string SearchURL, int PageLimit, int SearchEngineID, PerformContext context)
{
WebClient wc = new WebClient();
#region Main Table - SearchEngineTbl
var NewExtraction = db.SearchEngineTbls.Where(x => x.SearchEngineID == SearchEngineID).FirstOrDefault();
var JobID = context.BackgroundJob.Id;
NewExtraction.JobID = Convert.ToInt32(JobID);
NewExtraction.SeachEngineURL = SearchURL;
NewExtraction.Status = "Processing";
db.SaveChanges();
var LinkCollectionRefined = ExtractLinkFromThisPage(i, SearchURL, wc).Distinct().ToList();//.Skip(10);
foreach (var Link in LinkCollectionRefined)
{
using (Entities dbRefreshed = new Entities())
{
// I get the same old value here, even if I update the table manually, when I rerun, everything is fine.
var CurrentStatusOfExtraction = db.SearchEngineTbls.Where(x => x.SearchEngineID == NewExtraction.SearchEngineID).FirstOrDefault();
if (CurrentStatusOfExtraction.IsActive == false)
{
return;
}
}
}
#endregion
}

How can I fix my Castle Windsor registration?

I've tried so hard to make this work, but when I try to resolve IConfigReader from the container it says that I haven't registered any components. I've read through it over and over again. Baffled!
var builder = new ContainerBuilder();
builder.RegisterType<ConsoleLogger>().As<ILogger>();
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();
builder.Register(c => new ConfigReader("mysection")).As<IConfigReader>();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var reader = container.Resolve<IConfigReader>();
}

Using Autofac with webapi and mvc5.1 not working for webapi

I have a project using both mvc and webapi.
It's a Membership Reboot application so I have taken the example single application project and have slightly modified it to suit.
The DI works ok for controllers however when I try to call a webapi controller I keep getting an error
Make sure that the controller has a parameterless public constructor.
Is there something else I need to do for using autofac with webapi?
This is the code from my startup.cs
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "External",
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive
});
ConfigureMembershipReboot(app);
}
private static void ConfigureMembershipReboot(IAppBuilder app)
{
System.Data.Entity.Database.SetInitializer(new System.Data.Entity.MigrateDatabaseToLatestVersion<DefaultMembershipRebootDatabase, BrockAllen.MembershipReboot.Ef.Migrations.Configuration>());
//System.Data.Entity.Database.SetInitializer(new System.Data.Entity.CreateDatabaseIfNotExists<DefaultMembershipRebootDatabase>());
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationType = MembershipRebootOwinConstants.AuthenticationType
};
BuildAutofacContainer(app, cookieOptions.AuthenticationType);
app.UseMembershipReboot(cookieOptions);
}
private static void BuildAutofacContainer(IAppBuilder app, string authType)
{
var builder = new ContainerBuilder();
var config = CreateMembershipRebootConfiguration(app);
builder.RegisterInstance(config).As<MembershipRebootConfiguration>();
builder.RegisterType<DefaultUserAccountRepository>()
.As<IUserAccountRepository>()
.As<IUserAccountQuery>()
.InstancePerLifetimeScope();
builder.RegisterType<UserAccountService>().OnActivating(e =>
{
var owin = e.Context.Resolve<IOwinContext>();
var debugging = false;
#if DEBUG
debugging = true;
#endif
e.Instance.ConfigureTwoFactorAuthenticationCookies(owin.Environment, debugging);
})
.AsSelf()
.InstancePerLifetimeScope();
builder.Register(ctx =>
{
var owin = ctx.Resolve<IOwinContext>();
return new OwinAuthenticationService(authType, ctx.Resolve<UserAccountService>(), owin.Environment);
})
.As<AuthenticationService>()
.InstancePerLifetimeScope();
builder.Register(ctx=>HttpContext.Current.GetOwinContext()).As<IOwinContext>();
builder.RegisterControllers(typeof(Startup).Assembly);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
System.Web.Mvc.DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
It was a 1 liner :)
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);