Is there a way to create objects in HTTP module and pass those objects to applications.
I can use HTTPContext.Items. But that means I will reference System.Web in any DLL in the application that will use those data. Utility.dll is reading data generated by the http module, and I don't want to reference System.Web in that DLL because it is used by both web and desktop applications.
of course Desktop applications will not find the object, this is not a problem.
You can use the new and extensible cache API in System.Runtime.Caching, namely, the MemoryCache class. Just use a shared constant as the name and you're done.
I think your web module should communicate with Utility.dll and not the other way around. It should call a function inside Utility.dll with the data it needs. Since we don't know much about the nature of your application and that you didn't provide much information about how you want your different modules to communicate, it hard to give a definite answer.
The Utility.dll module could have a method accepting data like
public void QueueProcessingData(YourDataType[] data) {/* ... */}
If you really want your Utility.dll module to pull data from the web server, then you could use the builtin cache like #Ricardo Peres said. Example of using the builtin MemoryCache:
var data = "object your web module created and you want to pass to utility.dll";
ObjectCache cache = MemoryCache.Default;
cache.Add("The name you want", data, new CacheItemPolicy { AbsoluteExpiration = DateTime.MaxValue });
That way your other modules don't have to reference System.Web
HttpContext.Items is an IDictionary, so you can avoid a System.Web dependency in your common code by depending on that abstraction:
Utility.dll
class Util
{
static void DoStuff(IDictionary environment) { ... }
}
App.dll
class App
{
void DoStuff()
{
Util.DoStuff(new Hashtable { { "Foo", "Bar" } });
}
}
Web.dll
class MyModule : IHttpModule
{
void Init(HttpApplication context)
{
Util.DoStuff(context.Context.Items);
}
}
Thanks to #user1429080. it is kind of simple DI pattern.
Add an interface to Util.dll.
Add a reference to it in class Util add a property to access it.
The interface is implemented in WebUtil.dll. WebUtil is referencing System.Web.
In HttpModule.Init() I assign the implementation to the interface.
Util class is using the interface to read data generated from HttpModule instead of accessing System.Web.
Now I can have another source of data by creating another implementation for the interface.
Related
public class BasketService
{
IRepositoryBase baskets;
public const string BasketSession = "eCommerceBasket";
public BasketService(IRepositoryBase<Basket> baskets)
{
this.baskets = baskets;
}
private Basket CreateNewBasket(HttpContextBase httpContext)
{
}
}
If this is really what you want...
The HttpContextBase class is in the System.Web namespace. So you'll either need to fully-qualify the class name:
private Basket CreateNewBasket(System.Web.HttpContextBase httpContext)
{
}
or add the appropriate using directive at the top of your code file:
using System.Web;
If you then get an error that HttpContextBase isn't in that namespace or that the namespace doesn't exist, double-check that you've added the reference to your project. In the Solution Explorer in Visual Studio, right-click on the "References" node in the project and select "Add Reference". Navigate to the "Assemblies" to find and select System.Web. Click "OK".
Having said that... Are you sure this is the design you want? If your goal is to make a generic service which can be used by different applications, making that service depend on the web application would be ill-advised. What happens if you want to use it in a Console Application? There's no web context there.
Instead of making your general-purpose code depend on UI-specific things, turn that around. Make your UI-specific applications depend on the general-purpose code. So for this particular method, ask yourself...
What would I need to "create" a new "basket"?
Whatever information that is, that's what CreateNewBasket should accept as parameters. Maybe it's a handful of values, maybe it's a custom object, that's up to you. But "creating a basket" does not require an HTTP context. It requires some values that you are expecting to find in your HTTP context at a particular time.
The application layer should be responsible for pulling those values from the HTTP context and providing them to CreateNewBasket. The general-purpose code should just require the values themselves.
Currently have a Factory class that features a GetSelector function, which returns a concrete implementation of ISelector. I have several different classes that implement ISelector and based on a setting I would like to receive the appropriate ISelector back.
public interface ISelector
{
string GetValue(string Params);
}
public class XmlSelector : ISelector
{
public string GetValue(string Params)
{
// open XML file and get value
}
}
public static class SelectorFactory
{
public static ISelector GetSelector()
{
return new XmlSelector(); // Needs changing to look at settings
}
}
My question is what is the best way to store the setting? I am aware of using AppSettings etc. but I'm not sure whether I want to have to store strings in the web.config and perform a switch on it - just seems to be really tightly coupled in that if a new implementation of ISelector is made, then the Factory would need to be changed. Is there any way of perhaps storing an assembly name and instantiating based on that?
Thanks,
Chris
It is hard to say, because I don't know the architecture of your particular project, but at a first glance what I would do is if the objects associated with ISelector can be decoupled from your web application, I would put these objects in a class library along with the factory. Your factory will need to be changed if you implement a new ISelector, but if you can decouple the whole ISelector family from your actual web application the depth of the refactoring you will have to do will be minimal compared to a monolithic architecture.
Personally, I tend to avoid AppSettings, web.config settings and the like for mission-critical design questions. Using the web.config as an example, I have seen applications where architectural data is stored for ease of configurability. The problem is that after compilation your web.config can be changed (that is the purpose of it after all) and if the implementation of your classes depends on very specific values being chosen, you are running a risk of a crash when someone inadvertently modifies the wrong value.
Like I said all this depends entirely on your application architecture, but my reflex would be to split out the components that could be subject to future modification into a class library. Loose coupling is your friend ;).
Instead of doing it in AppSettings, I think a better approach will be to create a separate XML file, which will only hold the mappings and from that file you can iterate through the mappings and return correct instance in GetSelector().
I have a class which needs a string as a parameter in its constructor but this parameter will be decided by the calling code. At the same point of time, the life time of this class has to be tied to per HTTP request. So, I created a custom PerWebRequestTimelineManager and used that for my target type in the config file. But since the string in the constructor has to be dynamically determined, I cannot use the ConstructorInjection via the config file. I can use an abstract factory to solve the problem of dynamic dependency, but I am not sure about the implementation: Can you check the code below and validate the approach. Specifically the RegisterType and Resolve calls seem a bit out of place though the successive Resolve calls across the application will be able to retrieve the same instance.:
public class PerformanceTracerFactory : IPerformanceTracerFactory
{
private readonly IPerformanceTracer tracer;
public IPerformanceTracer CreateInstance(string operationTitle)
{
_container.RegisterType<IPerformanceTracer, PerformanceTracer>(new InjectionConstructor(operationTitle));
return _container.Resolve<IPerformanceTracer>();
}
}
Relevant portion of config file:
<register type="IPerformanceTracer" mapTo="PerformanceTracer">
<lifetime type="PerWebRequest"/>
</register>
<register type="IPerformanceTracerFactory" mapTo="PerformanceTracerFactory"/>
I have another question. In case if the above way of configuring and injecting the dependency using code is correct, then I think I do not need the config entries. I can always use the suitable overload to push the custom lifetime manager. In case, I would want to achieve the same thing using only config file, then how do I code the solution?
If you use a container-based factory you don't have to register/resolve your IPerformanceTracer in each call.
Register the mapping IPerformanceTracer --> PerformanceTracer once in your config file and use a ParameterOverride when you resolve your interface.
public IPerformanceTracer CreateInstance(string operationTitle)
{
return _container.Resolve<IPerformanceTracer>(new ParameterOverride("nameOfTheParameterInTheConstructorOfPerformanceTracer", operationTitle);
}
I am loading a type from an external assembly and want to create an instance of the type. However, this type/class is setup for constructor injection by objects currently being managed/bound by Ninject. How can I use Ninject to create an instance of this type and inject any constructor dependencies?
Below is how I get this type.
Assembly myAssembly = Assembly.LoadFrom("MyAssembly.dll");
Type type = myAssembly.GetType("IMyType");
Assuming you've created a Kernel, you should be able to create and have it resolved via:
kernel.Get(type)
.... then I read the question.... Assuming MyAssembly.dll has an implementation of IMyType, you need (in your main assembly) :-
kernel.Load( "MyAssembly.dll")
And in your dynamically loaded assembly:-
public class Module : StandardModule
{
public override void Load()
{
Bind<IMyType>().To<MyType>();
}
}
And dont forget to see if MEF is the answer here, as you dont want to go writing reams of explicit plugin management and/or detection logic if you can help it (but if you're just doing straightforward stuff and are only doing the Assembly.LoadFrom() for the purposes of asking the question, you're probably still in Ninject's sweet spot.
Ditto, if you actually need to resolve an interface via Assembly.GetType(), you probably should be using something like dynamic to do the late binding you'll probably have to do (and before you know it you should be using a dynamic language or hosting a scriopting language)
ASP.NET 3.5
Classes throughout our solution referenced ConfigurationManater.AppSettings[""] to get appSettings (from web.config).
We decided we weren't happy with that. Folks were mistyping appSetting key names in code (which compiled fine), and it was cumbersome to track usages. And then there's the duplicated strings throughout the codebase as you reference the same appSettings all over the place.
So, we decided that only one class would be allowed to reference the ConfigurationManager, and the rest of the solution would reference that class when it needed the value of a certain appSetting. ConfigurationManater.AppSettings[""] was static, so we exposed a bunch of static read-only properties off of our single Settings class.
public class Settings {
public static string Foo {
get {
return ConfigurationManager.AppSettings["Foo"];
}
}
}
That worked pretty well, until we needed to mock the settings in our tests. We created an interface to enable our mocking (was this a mistake of any kind?).
public interface ISettings {
string Foo {
get;
set;
}
}
public class Settings : ISettings {
public string Foo {
get {
return ConfigurationManager.AppSettings["Foo"];
}
}
}
And now we're injecting the ISettings instance as a dependency of the objects which use settings values (the class/interface are in a project that everyone can reference without problems).
In places where we can't inject an existing instance (e.g. Global.asax), we construct a new instance into a static field.
Given all of that, what would you recommend we change, and why?
Using an interface to represent configuration is a good idea. But your implementation looks a little off.
Joshua Flanagan wrote about writing application configuration code in a way that specific configuration sections can be injected into your code. This is a good idea, as it really decouples your code from worrying about details behind configuration. Have a read.
I think this will address the issue you are having re. testability.