I'm calling my custom factory that I created (PhotoServiceFactory), which is a singleton that allows me to get at a specific custom service type back (in this case FacebookService). FacebookService is also a singleton. In FacebookService I've exposed an instance of FacebookAlbumPhoto through a property. I did this because then I don't have to have a ton of the same code over and over again creating a new instance of FacebookAlbumPhoto...I can get an instance using the FacebookService's property.
PhotoServiceFactory service = PhotoServiceFactory.CurrentPhotoServiceFactory;
FacebookService facebookService = (FacebookService)service.GetAPIService(APIType.Facebook);
FacebookAlbumPhoto facebookPhoto = facebookService.FacebookAlbumPhoto.GetFacebookAlbumPhoto(selectedPhotoID);
So this is all set up now, I created all this and just testing it now.
What's happening is my code is bombing out at this line:
FacebookAlbumPhoto facebookPhoto = facebookService.FacebookAlbumPhoto.GetFacebookAlbumPhoto(selectedPhotoID);
The error I get is when I try to reference the facebookService.FacebookAlbumPhoto instance:
CurrentSession = '_singletonInstance.CurrentSession' threw an exception of type 'System.Threading.ThreadAbortException'
So I don't know if it's because the service singleton is on one thread and then it tries to reference another singleton that's on a completely different thread and that's just not possible? That it's not possible to nest singletons like this? Or could this be another issue altogether? Cause I can't see it.
Here's my ServiceFactory:
public class PhotoServiceFactory
{
private static PhotoServiceFactory _singletonInstance;
private PhotoServiceFactory(){}
public static PhotoServiceFactory CurrentPhotoServiceFactory
{
get
{
_singletonInstance = _singletonInstance ?? (_singletonInstance = new PhotoServiceFactory());
return _singletonInstance;
}
}
public object GetAPIService(APIType apiType)
{
object apiService = null;
switch (apiType)
{
case APIType.Facebook:
apiService = FacebookService.CurrentService;
break;
// rest of code
}
return apiService;
}
So the main singleton here Service has a property to get its related Session:
Here's the FacebookServiceClass:
public class FacebookService
{
private static FacebookService _singletonInstance;
private FacebookService(){}
public FacebookSession CurrentSession
{
get
{
return FacebookSession.GetCurrentSession();
}
}
/// <summary>
/// Gets the current facebook service singleton instance.
/// </summary>
/// <value>The current facebook service.</value>
public static FacebookService CurrentService
{
get
{
_singletonInstance = _singletonInstance ?? (_singletonInstance = new FacebookService());
return _singletonInstance;
}
}
public FacebookAlbumPhoto FacebookAlbumPhoto
{
get
{
return new FacebookAlbumPhoto(); // create an instance automatically so we can start working with this object
}
}
}
Here's the session class:
public class FacebookSession
{
const string loginCallbackUrl = "http://localhost/PhotoUpload/FacebookOauth.aspx";
private FacebookSession()
{
}
public string UserID { get; private set; }
public static FacebookSession GetCurrentSession()
{
//....bunch of other logic is here
FacebookSession facebookSession = CreateNewSession();
return facebookSession;
}
public FacebookSession CreateNewSession()
{
//...some code here
FacebookSession newFacebookSession = new FacebookSession
//... rest of code...
return newFacebookSession;
}
// ... rest of code
}
UPDATED:
As requested here's my FacebookAlbumPhoto class that I created:
public class FacebookAlbumPhoto : FacebookPhotoBase
{
private FacebookSession currentSession;
public FacebookAlbumPhoto()
{
currentSession = FacebookService.CurrentService.CurrentSession;
}
#region Methods
public FacebookAlbumPhoto GetFacebookAlbumPhoto(string photoID)
{
...more code
FacebookPhotoRequest request = new FacebookPhotoRequest(currentSession.UserID, photoID);
...more code
FacebookAlbumPhoto facebookPhoto = ParseFacebookPhoto(json);
return facebookPhoto;
}
...rest of code
}
Two things. First, remember to read over Skeet's catalogue of singleton implementations.
Second, try breaking your code just before the spot where the exception occurs, and then bring up your "Exception" dialogue (ctrl-alt-e). Click the "throw" checkbox next to the CLR (second row of dialogue) and hit ok. Continue debugging your code. The results may tell you where the real problem is.
Don't forgot to go back to the Exception dialogue and remove that check from the check box, after you are done. :)
separate instance creation from initialization
Related
I am creating a c# based automated testing framework and have configuration files that link test case methods and class names to requirement IDs. The framework will create a TestPlan that is a list of multiple test cases that will executed one after another.
Since there are thousands of testcases (and more all the time) I want to call these classes and methods by reflection, but I am concerned that these methods will create singleton instances of supporting classes that will hang around after the method returns that won't be reused when the next test method is called by reflection.
My question is: will each call use the same static instance in the assembly? Or will each call create a new instance of the singleton? Without reflection in the mix it is a simple answer, but with it ... I am not certain.
Example: I will call SomePageTestCases.TestcaseMethod1() by reflection below. This creates a static instance of CurrentPage which contains the Page object used by the TestMethod. After the Testcase returns, what happens if I call another TestMethod in another class by reflection? Does the CurrentPage.Instance persist and will it be used by the newly called test method? Or will it original be orphaned in the assembly and a new static instance of CurrentPage be created by the new test methods call?
namespace Framework.TestCases
{
public class SomePageTestCases
{
public bool TestCaseMethod1()
{
return (CurrentPage.Instance.Page as SomePage)?.DoSomething() ?? false;
}
}
}
namespace Framework
{
public class CurrentPage
{
private object TopLevelControl;
private static CurrentPage _instance;
public static CurrentPage Instance => _instance ?? (_instance = new CurrentPage());
private Page _page;
public Page Page
{
get
{
if (_page == null || _page.Name != GetCurrentPageName())
_page = GetCurrentPage();
return _page;
}
}
private CurrentPage()
{
//hooks the top level control of the system under test.
throw new NotImplementedException();
}
private static string GetCurrentPageName()
{
//return the page name of the current page from the TopLevelControl.
throw new NotImplementedException();
}
private static Page GetCurrentPage()
{
//Searches the TopLevelControl for the current PageObject and returns it.
throw new NotImplementedException();
}
}
}
namespace Framework.Base
{
public abstract class Page
{
public string Name { get; private set; }
public object PageObject { get; private set; }
protected void LoadPage(string pageClassName)
{
throw new NotImplementedException();
//Name = something;
//PageObject = something;
}
}
}
namespace Framework.Pages
{
public class SomePage : Page
{
public bool DoSomething()
{
throw new NotImplementedException();
}
public SomePage()
{
LoadPage("SomePage");
}
}
}
We're using a library that uses pooled objects (ServiceStack.Redis's PooledRedisClientManager). Objects are created and reused for multiple web requests. However, Dispose should be called after each use to release the object back into the pool.
By default, Ninject only deactivates an object reference if it has not been deactivated before.
What happens is that the pool instantiates an object and marks it as active. Ninject then runs the activation pipeline. At the end of the request (a web request), Ninject runs the deactivation pipeline which calls Dispose (and thus the pool marks the object as inactive). The next request: the first pooled instance is used and the pool marks it as active. However, at the end of the request, Ninject does not run its deactivation pipeline because the ActivationCache has already marked this instance as deactivated (this is in the Pipeline).
Here's a simple sample that we've added in a new MVC project to demonstrate this problem:
public interface IFooFactory
{
IFooClient GetClient();
void DisposeClient(FooClient client);
}
public class PooledFooClientFactory : IFooFactory
{
private readonly List<FooClient> pool = new List<FooClient>();
public IFooClient GetClient()
{
lock (pool)
{
var client = pool.SingleOrDefault(c => !c.Active);
if (client == null)
{
client = new FooClient(pool.Count + 1);
client.Factory = this;
pool.Add(client);
}
client.Active = true;
return client;
}
}
public void DisposeClient(FooClient client)
{
client.Active = false;
}
}
public interface IFooClient
{
void Use();
}
public class FooClient : IFooClient, IDisposable
{
internal IFooFactory Factory { get; set; }
internal bool Active { get; set; }
internal int Id { get; private set; }
public FooClient(int id)
{
this.Id = id;
}
public void Dispose()
{
if (Factory != null)
{
Factory.DisposeClient(this);
}
}
public void Use()
{
Console.WriteLine("Using...");
}
}
public class HomeController : Controller
{
private IFooClient foo;
public HomeController(IFooClient foo)
{
this.foo = foo;
}
public ActionResult Index()
{
foo.Use();
return View();
}
public ActionResult About()
{
return View();
}
}
// In the Ninject configuration (NinjectWebCommon.cs)
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IFooFactory>()
.To<PooledFooClientFactory>()
.InSingletonScope();
kernel.Bind<IFooClient>()
.ToMethod(ctx => ctx.Kernel.Get<IFooFactory>().GetClient())
.InRequestScope();
}
The solutions that we've come up with thus far are:
Mark these objects as InTransientScope() and use other deactivation mechanism (like an MVC ActionFilter to dispose of the object after each request). We'd lose the benefits of Ninject's deactivation process and require an indirect approach to disposing of the object.
Write a custom IActivationCache that checks the pool to see if the object is active. Here's what I've written so far, but I'd like some one else's eyes to see how robust it is:
public class PooledFooClientActivationCache : DisposableObject, IActivationCache, INinjectComponent, IDisposable, IPruneable
{
private readonly ActivationCache realCache;
public PooledFooClientActivationCache(ICachePruner cachePruner)
{
realCache = new ActivationCache(cachePruner);
}
public void AddActivatedInstance(object instance)
{
realCache.AddActivatedInstance(instance);
}
public void AddDeactivatedInstance(object instance)
{
realCache.AddDeactivatedInstance(instance);
}
public void Clear()
{
realCache.Clear();
}
public bool IsActivated(object instance)
{
lock (realCache)
{
var fooClient = instance as FooClient;
if (fooClient != null) return fooClient.Active;
return realCache.IsActivated(instance);
}
}
public bool IsDeactivated(object instance)
{
lock (realCache)
{
var fooClient = instance as FooClient;
if (fooClient != null) return !fooClient.Active;
return realCache.IsDeactivated(instance);
}
}
public Ninject.INinjectSettings Settings
{
get
{
return realCache.Settings;
}
set
{
realCache.Settings = value;
}
}
public void Prune()
{
realCache.Prune();
}
}
// Wire it up:
kernel.Components.RemoveAll<IActivationCache>();
kernel.Components.Add<IActivationCache, PooledFooClientActivationCache>();
Specifically for ServiceStack.Redis's: use the PooledRedisClientManager.DisposablePooledClient<RedisClient> wrapper so we always get a new object instance. Then let the client object become transient since the wrapper takes care of disposing it. This approach does not tackle the broader concept of pooled objects with Ninject and only fixes it for ServiceStack.Redis.
var clientManager = new PooledRedisClientManager();
kernel.Bind<PooledRedisClientManager.DisposablePooledClient<RedisClient>>()
.ToMethod(ctx => clientManager.GetDisposableClient<RedisClient>())
.InRequestScope();
kernel.Bind<IRedisClient>()
.ToMethod(ctx => ctx.Kernel.Get<PooledRedisClientManager.DisposablePooledClient<RedisClient>>().Client)
.InTransientScope();
Is one of these approaches more appropriate than the other?
I have not use Redis so far so I can not tell you how to do it correctly. But I can give you some input in general:
Disposing is not the only thing that is done by the ActivationPipeline. (E.g. it also does property/method injection and excuting activation/deactivation actions.) By using a custom activation cache that returns false even though it has been activated before will cause that these other actions are executed again (E.g. resulting in property injection done again.)
I'm using the Singleton design pattern and I must return the object if it hasn't been used before.
I get an exception in the following code :
namespace app.Models
{
public class Conexion:DbContext
{
private static Conexion Instance = null;
private Conexion(string con) : base(con) { }
public static Conexion MainConexion
{
get {//error here
if (Instance == null)
{
Instance = new Conexion(#"Server=*****; User Id=***;Password=****; Database=****");
}
return Instance;
}
}
public DbSet<label> Labels { get; set; }
public DbSet<checke_status> CheckStatus { get; set; }
public void SaveChanges()
{
MainConexion.SaveChanges();
}
}
}
How can I solve this?
Remove the override of the SaveChanges method:
namespace app.Models
{
public class Conexion : DbContext
{
private static Conexion Instance = null;
private Conexion(string con) : base(con) { }
public static Conexion MainConexion
{
get
{ //error here
if (Instance == null)
{
Instance = new Conexion(
#"Server=*****; User Id=***;Password=****; Database=****");
}
return Instance;
}
}
public DbSet<label> Labels { get; set; }
public DbSet<checke_status> CheckStatus { get; set; }
}
}
Since you have a private constructor, the only instance of this class that can be used is the one exposed in the MainConexion property. It looks like you were trying to make sure that when any instance's SaveChanges method was called that the SaveChanges method on the MainConnection property's instance was called. This is not necessary, because you can only ever have one instance of the Conexion class, and it's the instance that you want to call SaveChanges on. The usage is still the same:
Conexion.MainConexion.SaveChanges();
That being said, I think you would have better luck if you were to not implement it this way. It would probably be better to open and close connections as they were needed, rather than rely on a single connection instance. What happens if the connection is interrupted? Rather than getting a single error, your application will be broken.
If you have multiple properties that implement the same method in the setter, is there a way to make it part of the default setter?
If I have multiple properties that call a Filter() when they are set, is there a way to push it into a "base setter" so that I don't have to have the Filter() call in every setter?
private string _MyVal1;
public string MyVal1 {
get {
return _MyVal1;
}
set {
_MyVal1 = value;
Filter();
OnPropertyChanged("MyVal1");
}
}
private string _MyVal2;
public string MyVal2 {
get {
return _MyVal2;
}
set {
_MyVal2 = value;
Filter();
OnPropertyChanged("MyVal2");
}
}
private string _MyValN;
public string MyValN {
get {
return _MyValN;
}
set {
_MyValN = value;
Filter();
OnPropertyChanged("MyValN");
}
}
So it turns into this:
private string _MyValN;
public string MyValN {
get {
return _MyValN;
}
set : FilterSetter {
_MyValN = value;
OnPropertyChanged("MyValN");
}
}
A different way of doing this is to use interception like that provided by the Unity framework. With interception your class implements an interface and you would tell the framework that everytime a method is called on classes implementing that interface, run these interceptors. Your interceptors code can look to see if the method being called is prefixed with set_. Interceptor code executes once on the way to the function and once on the way back. On the way back, you can then have the interceptor call the filter method (assuming it is defined on the interface of course).
Concrete example:
Get Prerequisite Library
Use NuGet to add Unity and Unity extensions to your project
Define your interface to be intercepted: SomeObject.cs
using System;
namespace InterceptSetter
{
interface ISomeObject
{
string SomeProperty { get; set; }
void Filter();
}
public class SomeObject : ISomeObject
{
public string SomeProperty { get; set; }
public void Filter()
{
Console.Out.WriteLine("Filter Called");
}
}
}
Define your Interception Behavior: SetterCallsFilterMethodBehavior.cs
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Collections.Generic;
using System.Linq;
namespace InterceptSetter
{
/// <summary>
/// See http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx
/// See http://msdn.microsoft.com/en-us/library/ff647107.aspx
/// </summary>
class SetterCallsFilterMethodBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
// we dont need anything
return new[] { typeof(ISomeObject) };
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{ // Do not intercept non-setter methods
if (!input.MethodBase.Name.StartsWith("set_"))
return getNext()(input, getNext);
IMethodReturn msg = getNext()(input, getNext);
// post processing. this is where we call filter
if (input.Target is ISomeObject)
{
(input.Target as ISomeObject).Filter();
}
return msg;
}
/// <summary>
/// We always execute
/// </summary>
public bool WillExecute
{
get { return true; }
}
}
}
Write a test console program: Program.cs
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
namespace InterceptSetter
{
class Program
{
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<ISomeObject, SomeObject>(
new Interceptor<TransparentProxyInterceptor>(),
new InterceptionBehavior<SetterCallsFilterMethodBehavior>());
// we must get our instance from unity for interception to occur
ISomeObject myObject = container.Resolve<ISomeObject>();
myObject.SomeProperty = "Hello Setter";
Console.ReadLine();
}
}
}
Running this you will see that the interceptor does in fact call the filter method (which prints to the console).
Unity is not the only dependency injection / interception framework out there (google PostSharp). Unity is the one i am familiar with so thats what this example uses.
Sources / See Also:
http://msdn.microsoft.com/en-us/library/ff660871(v=pandp.20).aspx - Good diagram depicting the flow of interception
http://msdn.microsoft.com/en-us/library/ff647107.aspx - overkill of detail showing different interception techniques
You can create generic setter method and call that from each property setter:
private void Set<T>(ref T field, T value, string propertyName)
{
field = value;
Filter();
OnPropertyChanged(propertyName);
}
Then your properties look like:
public string SomeProperty
{
get { return this.someField; }
set
{
Set(ref this.someField, value, "SomeProperty");
}
}
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
In page_load event i am calling
if (mySession.Current._isCustomer)
{
Response.Redirect("Products.aspx");
}
mySession class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ShoppingCartWebApp
{
public class mySession
{
// private constructor
private mySession() {}
// Gets the current session.
public static mySession Current
{
get
{
mySession session =
(mySession)HttpContext.Current.Session["__MySession__"];
if (session == null)
{
session = new mySession();
HttpContext.Current.Session["__MySession__"] = session;
}
return session;
}
}
// **** add your session properties here, e.g like this:
public string _Property1 { get; set; }
public DateTime _date { get; set; }
public String _loginId { get; set; }
public string _firstName { get; set; }
public string _userName { get; set; }
public string _role { get; set; }
public Boolean _isCustomer = false;
public Boolean _isAuth = false;
public Boolean _isGuest = true;
public ShoppingCart _cart = new ShoppingCart();
public ShoppingCart instance
{
get
{
return _cart;
}
set
{
_cart = value;
}
}
public void abandonSession()
{
// _date =
_loginId = null;
_firstName = null;
_cart = null;
_userName = null;
_role = null;
_isCustomer = false;
_isAuth = false;
}
}
}
it gives a stackoverflow exception. why?
ShoppingCart Class:
public class ShoppingCart
{
#region ListCart
public List<CartItem> Items { get; private set; }
public static SqlConnection conn = new SqlConnection(connStr.connString);
#endregion
#region CartSession
public ShoppingCart cart;
public ShoppingCart()
{
if (mySession.Current._cart == null)
{
cart = new ShoppingCart();
cart.Items = new List<CartItem>();
if (mySession.Current._isCustomer)
cart.Items = ShoppingCart.loadCart(mySession.Current._loginId);
mySession.Current._cart = cart;
}
else
{
cart = mySession.Current._cart;
}
}
}
This line of code causes infinite loop and stack overflow :
if (mySession.Current._isCustomer)
cart.Items = ShoppingCart.loadCart(mySession.Current._loginId);
it is initialized by each instance of mysession class. and its using its parent class.
even using singleton mySession can not solve the problem.
when this code is executing :
session = new mySession();
it tries to initialize new ShoppingCard. shopping card asks for singleton instance of mysession. this line of code is not executed yet :
HttpContext.Current.Session["__MySession__"] = session;
so goes to create a new instance of my session and ...
this means stack overflow !
you can correct it like this :
public static mySession Current
{
get
{
mySession session =
(mySession)HttpContext.Current.Session["__MySession__"];
if (session == null)
{
session = new mySession();
HttpContext.Current.Session["__MySession__"] = session;
session._cart = new ShoppingCart(); //initialize your shoppoing car after adding variable to session !
}
return session;
}
}
public ShoppingCart _cart;// = new ShoppingCart(); remove initialization
look at my comments in code.
The problem comes because of the relationship between mySession and ShoppingCart.
mySession has a member variable defined like so:
public ShoppingCart _cart = new ShoppingCart();
When the constructor of mySession is called, an instance of ShoppingCart is instantiated. When the constructor of ShoppingCart executes, it calls the mySession.Current static property. Because the constructor of ShoppingCart was called from within this same property (remember, we are still creating an instance of mySession in the original static call), it continues to recurse in this way until a StackOverflowException is raised.
To fix this, I suggest you take a look at your ShoppingCart class. Firstly, why does it need an instance of itself as a member variable? Secondly, if ShoppingCart needs to know information about the contents of mySession, your encapsulation is not correct. I suggest you pass the information needed into the constructor of ShoppingCart to avoid making a call back to mySession.Current.
Given your updated question, I think if you properly followed .Net naming guidelines (as outlined in my comment on your question), you should be able to easily figure out where the problem is. I suspect your calling code is similar, and not following the guidelines is obscuring what is actually happening from what you think is happening.
As a first step I would recommend doing this cleanup; it will likely make it clear where you're causing the overflow.