AppDomain.Unload does not remove lock on dll - appdomain

am using the following code to create new AppDomain and load my assemblies into it, where my assemblies load successfully, but after i call the AppDomain.Unload method, there is still lock on the loaded dlls, where i went for creating new AppDomain solution because i found over the net that this is the recommended technique to load/unload assemblies and also to make the assemblies replaceable, any idea?
here is my code:
public sealed class AssemblyLoader : MarshalByRefObject
{
private static AppDomain LocalDomain = AppDomain.CreateDomain("LocalDomain");
public static Assembly LoadAssembly(string path)
{
try
{
Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(path));
if (assembly != null)
return assembly;
}
catch { }
return Assembly.LoadFrom(path);
}
public static void Unload()
{
if (LocalDomain != null)
{
AppDomain.Unload(LocalDomain);
LocalDomain = null;
}
}
}

I'm not sure but from the theory shouldn't it be more like this.
You're not loading the assembly through the newly created AppDomain.
public static Assembly LoadAssembly(string path)
{
try
{
Assembly assembly = LocalDomain.Load(AssemblyName.GetAssemblyName(path));
if (assembly != null)
return assembly;
}
catch { }
// ..
}

Related

NHibernate Spatial Mapping returns Antrl error

I am using NHibernate 3.3. I have a case where I want to insert a calculated column which is not referenced.
My Domain Entity can be reduced to the form
public class Location
{
public virtual IPoint GeoLocation {get;set;}
}
public class MappingOverride : IAutoMappingOverride<Location>
{
public void Override(AutoMapping<Location> mapping)
{
mapping
.Map(e => e.GeoLocation)
.Column("GeoLocation")
.CustomSqlType("geography")
.CustomType<MsSql2008GeographyType>;
}
}
The table column is of type 'Geography`
However it errors out as
at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes)
at System.Reflection.RuntimeAssembly.GetExportedTypes()
at GeoAPI.GeometryServiceProvider.GetLoadableTypes(Assembly assembly)
at GeoAPI.GeometryServiceProvider.ReflectInstance()
at GeoAPI.GeometryServiceProvider.get_Instance()
at NetTopologySuite.Geometries.Geometry.set_SRID(Int32 value)
It says that it needs Antrl.Runtime, but a very old version. All the Antrl.Runtime nuget packages out there have a different assembly identifier.
Could not load file or assembly 'antlr.runtime, Version=2.7.6.2, Culture=neutral, PublicKeyToken=1790ba318ebc5d56' or one of its dependencies. The system cannot find the file specified.
I worked on a separate project where I used map by code convention and it works without any reference to Antrl.Runtime.
Need help to point myself in the right direction...
As a separate sample project I tried something which worked, WHICH DID NOT WORK in the actual ASP.NET MVC project.
Definition of Class
public class Location : IEntity
{
public virtual int Id { get; protected set; }
public virtual string LocationName { get; set; }
public virtual IPoint GeoLocation { get; set; }
}
Mapping
public class LocationMapping : IAutoMappingOverride<Location>
{
public void Override(AutoMapping<Location> mapping)
{
mapping.Map(x => x.LocationName).Column("Name");
mapping.Map(x => x.GeoLocation).Column("GeoLocation")
.CustomType<MsSql2008GeographyType>();
}
}
Test
public class WhenSavingGeoLocation : BasePersistanceTest
{
[Test]
public void Save()
{
this.Session
.SaveOrUpdate(new Location {
LocationName = "Category 01",
GeoLocation = new Point(-72.12, 32.2323234) { SRID = 4326 }
});
}
}
NHibernate.Spatial uses NetTopologicalSuite which itself is a derivative of GeoAPI
The GeoAPI library defines an interface GeoAPI.Geometries and while loading / searching the correct implementation in the current project was failing with the Antlr error in the MVC project.
It was however able to fetch the NetTopologySuite.NtsGeometryServices implementation in the separate sample project. The actual code in GeoAPI which searches for the implementation goes like
private static IGeometryServices ReflectInstance()
{
#if !PCL
var a = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in a)
{
// Take a look at issue 114: http://code.google.com/p/nettopologysuite/issues/detail?id=114
if (assembly is System.Reflection.Emit.AssemblyBuilder) continue;
if (assembly.GetType().FullName == "System.Reflection.Emit.InternalAssemblyBuilder") continue;
if (assembly.GlobalAssemblyCache && assembly.CodeBase == Assembly.GetExecutingAssembly().CodeBase) continue;
foreach (var t in GetLoadableTypes(assembly))
{
if (t.IsInterface) continue;
if (t.IsAbstract) continue;
if (t.IsNotPublic) continue;
if (!typeof(IGeometryServices).IsAssignableFrom(t)) continue;
var constuctors = t.GetConstructors();
foreach (var constructorInfo in constuctors)
{
if (constructorInfo.IsPublic && constructorInfo.GetParameters().Length == 0)
return (IGeometryServices)Activator.CreateInstance(t);
}
}
}
#endif
throw new InvalidOperationException("Cannot use GeometryServiceProvider without an assigned IGeometryServices class");
}
}
This gets called when setting the SRID on the geometry. I am guessing that my MVC project has a reference to an assembly which makes this look for Antlr.
There were some suggestions of adding a redirect for to newer Antlr assembly. I tried that as well but the error still kept repeating.

Query FxCop For Supported Rules (Using commandline)

I would like to run a command to see all rules that FxCop will support (based on the DLLs in its Rules directory).
Is this possible?
The rule list can be viewed in the Rules tab of the FxCop UI (e.g.: http://www.binarycoder.net/fxcop/html/screenshot.png).
If you want a text version and don't have a screen clipping tool that will allow you to extract this from the UI, the rules list is pretty trivial to extract with a bit of reflection. You can either invoke internal types and methods in the FxCop object model to do this, or you can look for concrete classes that implement the Microsoft.FxCop.Sdk.IRule interface in the rule assemblies. e.g.:
internal static class Program
{
private static void Main(string[] args)
{
Program.EnumerateFxCopRules(#"C:\Program Files (x86)\Microsoft Fxcop 10.0\Rules");
Console.ReadLine();
}
private static void EnumerateFxCopRules(string ruleDirectoryPath)
{
foreach (var ruleAssembly in Program.GetAssemblies(ruleDirectoryPath))
{
Program.WriteRuleList(ruleAssembly);
}
}
private static IEnumerable<Assembly> GetAssemblies(string directoryPath)
{
var result = new List<Assembly>();
foreach (var filePath in Directory.GetFiles(directoryPath, "*.dll"))
{
try
{
result.Add(Assembly.LoadFrom(filePath));
}
catch (FileLoadException)
{
Console.WriteLine("FileLoadException attempting to load {0}.", filePath);
}
catch (BadImageFormatException)
{
Console.WriteLine("BadImageFormatException attempting to load {0}.", filePath);
}
}
return result;
}
private static void WriteRuleList(Assembly ruleAssembly)
{
Console.WriteLine(ruleAssembly.Location);
foreach (var ruleType in ruleAssembly.GetTypes().Where(t => (!t.IsAbstract) && typeof(IRule).IsAssignableFrom(t)))
{
Console.WriteLine("\t{0}", ruleType.FullName);
}
}
}

Using PostSharp OnExceptionAspect across mulit projects

Good afternoon everyone,
I am trying to use the example "Aspect Oriented Programming Using C# and PostSharp" by Reza Ahmadi
http://www.codeproject.com/Articles/337564/Aspect-Oriented-Programming-Using-Csharp-and-PostS and dnrTV http://dnrtv.com/dnrtvplayer/player.aspx?ShowNum=0190 for the exception handling. Everything works great if the "OnExceptionAspect" is in the same project/assembly, however the event does not work if it I move the class to it own dll.
[assembly: ExceptionAspect (AttributePriority = 1)]
[assembly: ExceptionAspect(AttributePriority = 2, AttributeExclude = true, AttributeTargetTypes = "HpsErp.Common.AspectObject.*")]
namespace AspectObject
[Serializable]
public class ExceptionAspect : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
Trace.TraceError("{0} in {1}.{2}",
args.Exception.GetType().Name,
args.Method.DeclaringType.FullName,
args.Method.Name);
if (args.Instance != null)
{
Trace.TraceInformation("this={0}", args.Instance);
}
foreach (ParameterInfo parameter in args.Method.GetParameters())
{
Trace.TraceInformation("{0}={1}", parameter.Name,
args.Arguments[parameter.Position] ?? "null");
}
}
I also created a class in the external dll for "Timing" and it works great if I add a custom attribute to the class.
namespace AspectObject
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method)]
public class TimingAspect : OnMethodBoundaryAspect
{
[NonSerialized]
Stopwatch _StopWatch;
public override void OnEntry(MethodExecutionArgs args)
{
_StopWatch = Stopwatch.StartNew();
base.OnEntry(args);
}
public override void OnExit(MethodExecutionArgs args)
{
Console.WriteLine(string.Format("[{0}] took {1}ms to execute",
new StackTrace().GetFrame(1).GetMethod().Name,
_StopWatch.ElapsedMilliseconds));
base.OnExit(args);
}
Using AspectObject;
namespace MyApp
{
public class Car
{
[TimingAspect]
private void Drive()
{
//...
}
}
}
In the end, I am hoping to have this is multi dlls so that I can reuse it ie: wcf.
Thanks for any and all help...
James
You can access your aspects if they are stored in a separate DLL.
I always create a DLL class project called Aspects. In the projects I want AOP, I add a reference to that dll class. Then decorate your methods/class/assembly like you normally do.
https://github.com/sharpcrafters/PostSharp-Toolkits <-- good examples
http://researchaholic.com/tag/postsharp/ <-- some more examples, just uploaded an example

Can't get Ninject.Extensions.Interception working

I've been trying for ages to figure this our. when i try to bind my class with an interceptor i'm getting the following exception on the line
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
Error loading Ninject component IAdviceFactory. No such component has been registered in the kernel's component container
I've tried with and without LoadExtensions, With about with using a Module to set up my bindings and my last attempt looks like this
internal class AppConfiguration
{
internal AppConfiguration( )
{
var settings = new NinjectSettings() { LoadExtensions = false };
Kernel = new StandardKernel(settings);
Load();
}
internal StandardKernel Kernel { get; set; }
public static AppConfiguration Instance
{
get { return _instance ?? (_instance = new AppConfiguration()); }
}
private static AppConfiguration _instance;
private void Load()
{
Kernel.Bind<ILoggerAspect>().To<Log4NetAspect>().InSingletonScope();
Kernel.Bind<MyClass>().ToSelf().Intercept().With<ILoggerAspect>();
}
internal static StandardKernel Resolver()
{
return Instance.Kernel;
}
}
My Logger Attribute looks like this
public class LogAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
return request.Context.Kernel.Get<ILoggerAspect>();
}
}
And my interceptor like this
public class Log4NetAspect : SimpleInterceptor, ILoggerAspect
{
protected override void BeforeInvoke(IInvocation invocation)
{
Debug.WriteLine("Running " + invocation.ReturnValue);
base.BeforeInvoke(invocation);
}
public new void Intercept(IInvocation invocation)
{
try
{
base.Intercept(invocation);
}
catch (Exception e)
{
Debug.WriteLine("Exception: " + e.Message);
}
}
protected override void AfterInvoke(IInvocation invocation)
{
Debug.WriteLine("After Method");
base.AfterInvoke(invocation);
}
}
Most likely you didn't deploy Ninject.Extensions.Interception.DynamicProxy or Ninject.Extensions.Interception.Linfu alongside your application [and Ninject.Extensions.Interception]. You have to pick exactly one of them.
With the code as you have it right now (LoadExtensions=false) it will fail to pick up the specific interception library - you should remove that and the normal extensions loading should wire the extension into the Kernel on creation for the interception bits to pick it up.
In addition to Remo Gloor's answer which pointed me toward adding the nuget package for Ninject.Extensions.Interception.DynamicProxy, I kept getting the same exception as the OP, until I manually loaded a DynamicProxyModule - the FuncModule is manually loaded as well, to work around a similar error involving the factory extension:
_kernel = new StandardKernel(
new NinjectSettings{LoadExtensions = true},
new FuncModule(),
new DynamicProxyModule()); // <~ this is what fixed it

CodeCampServer don't input any logging from NHibernate?

Are you ever succeed input NHibernate logging using CodeCampServer architecture?
I read this and I did everything that I can. Maybe there is know problem in this architecture.
I using Infrastructure.NHibernate.DataAccess.Bases.Logger.EnsureInitialized();
to initialize log4net. here the code:
public class DependencyRegistrar
{
private static bool _dependenciesRegistered;
private static void RegisterDependencies()
{
ObjectFactory.Initialize(x => x.Scan(y =>
{
y.AssemblyContainingType<DependencyRegistry>();
y.AssemblyContainingType<NaakRegistry>();
y.LookForRegistries();
y.AddAllTypesOf<IRequiresConfigurationOnStartup>();
}));
new InitiailizeDefaultFactories().Configure();
}
private static readonly object sync = new object();
internal void ConfigureOnStartup()
{
Infrastructure.NHibernate.DataAccess.Bases.Logger.EnsureInitialized();
RegisterDependencies();
var dependenciesToInitialized = ObjectFactory.GetAllInstances<IRequiresConfigurationOnStartup>();
foreach (var dependency in dependenciesToInitialized)
{
dependency.Configure();
}
}
public static T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
public static object Resolve(Type modelType)
{
return ObjectFactory.GetInstance(modelType);
}
public static bool Registered(Type type)
{
EnsureDependenciesRegistered();
return ObjectFactory.GetInstance(type) != null;
}
public static void EnsureDependenciesRegistered()
{
if (!_dependenciesRegistered)
{
lock (sync)
{
if (!_dependenciesRegistered)
{
RegisterDependencies();
_dependenciesRegistered = true;
}
}
}
}
}
And I see the logging files, I can't delete them when the app run, so I know they are generated. in addition, when I log for test, the log are input. For example, this code do input log.
Bases.Logger.Debug(this, "Debug test!")
So, do CodeCampServer have a architecture problem with log4net?
The post looks correct to me.
Are you sure you added the necessary assembly level attribute?
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
If this won't work maybe you should try:
log4net.Config.XmlConfigurator.Configure();
for example in your Application_Start of Global.asax.
If this won't work please post your example code.
Accidentally found solution by replacing the reference forlog4net.dll to the on that come with NHibernate bins, instead the own log4net.
Wired, but I have logs... :)