This commit is contained in:
Eugene Sadovoi 2019-06-13 21:57:09 -04:00
Родитель fb6139d6e9
Коммит ff04af20dd
4 изменённых файлов: 116 добавлений и 61 удалений

Просмотреть файл

@ -1,4 +1,5 @@
using System;
using System.Reflection;
namespace Unity.Exceptions
{
@ -22,5 +23,11 @@ namespace Unity.Exceptions
Data.Add(Guid.NewGuid(), info);
}
internal InvalidRegistrationException(string message, ParameterInfo info)
: base(message)
{
Data.Add(Guid.NewGuid(), info.ParameterType);
Data.Add(Guid.NewGuid(), info);
}
}
}

Просмотреть файл

@ -7,6 +7,7 @@ using System.Reflection;
using System.Text.RegularExpressions;
using Unity.Exceptions;
using Unity.Injection;
using Unity.Lifetime;
using Unity.Resolution;
namespace Unity
@ -292,22 +293,85 @@ namespace Unity
ResolveDelegate<PipelineContext>? pipeline,
bool perResolve)
{
var resolver = base.GetResolverDelegate(info, resolvers, pipeline, perResolve);
return (ref PipelineContext context) =>
try
{
try
{
// TODO: Add validation
// Create parameter resolvers
var parameterResolvers = ParameterResolvers(info.GetParameters(), resolvers).ToArray();
return resolver(ref context);
}
catch (Exception ex)
// Select Lifetime type ( Per Resolve )
if (perResolve)
{
ex.Data.Add(Guid.NewGuid(), info);
throw;
// Activate type
return (ref PipelineContext context) =>
{
if (null == context.Existing)
{
try
{
var dependencies = new object[parameterResolvers.Length];
for (var i = 0; i < dependencies.Length; i++)
dependencies[i] = parameterResolvers[i](ref context);
context.Existing = info.Invoke(dependencies);
context.Set(typeof(LifetimeManager), new RuntimePerResolveLifetimeManager(context.Existing));
}
catch (Exception ex)
{
ex.Data.Add(Guid.NewGuid(), info);
throw;
}
}
// Invoke other initializers
return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
};
}
};
else
{
// Activate type
return (ref PipelineContext context) =>
{
if (null == context.Existing)
{
try
{
var dependencies = new object[parameterResolvers.Length];
for (var i = 0; i < dependencies.Length; i++)
dependencies[i] = parameterResolvers[i](ref context);
context.Existing = info.Invoke(dependencies);
}
catch (Exception ex)
{
ex.Data.Add(Guid.NewGuid(), info);
throw;
}
}
// Invoke other initializers
return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
};
}
}
catch (InvalidRegistrationException ex)
{
// Throw if try to create
return (ref PipelineContext context) =>
{
if (null == context.Existing) throw ex;
return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
};
}
catch (Exception ex)
{
// Throw if try to create
return (ref PipelineContext context) =>
{
if (null == context.Existing) throw new InvalidRegistrationException(ex);
return null == pipeline ? context.Existing : pipeline.Invoke(ref context);
};
}
}
#endregion

Просмотреть файл

@ -1,6 +1,7 @@
using System;
using Unity;
using Unity.Registration;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using Unity.Resolution;
namespace Unity
@ -11,42 +12,43 @@ namespace Unity
public override ResolveDelegate<PipelineContext>? Build(ref PipelineBuilder builder)
{
var requestedType = builder.Type;
if (builder.Policies is ExplicitRegistration registration)
{
// Explicit Registration
if (null == registration.Type) return builder.Pipeline();
builder.Type = (null == registration.BuildType)
? registration.Type
: registration.BuildType(registration.Type);
}
else
{
// Implicit Registration
if (null != builder.TypeConverter)
builder.Type = builder.TypeConverter(builder.Type);
}
// If nothing to map or build required, just create it
if (builder.BuildRequired || requestedType == builder.Type)
return builder.Pipeline();
var pipeline = base.Build(ref builder);
var type = builder.Type;
return builder.Pipeline((ref PipelineContext context) =>
if (requestedType == type) return pipeline;
Debug.Assert(null != pipeline);
return (ref PipelineContext context) =>
{
try
{
return context.Resolve(type);
return pipeline(ref context);
}
catch (Exception ex)
{
ex.Data.Add(Guid.NewGuid(), new Tuple<Type, Type>(requestedType, type));
throw;
}
});
};
}
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
var requestedType = builder.Type;
var expressions = base.Express(ref builder);
var type = builder.Type;
if (requestedType == type) return expressions;
var tryBlock = Expression.Block(expressions);
var catchBlock = Expression.Block(tryBlock.Type,
Expression.Call(ExceptionDataExpr, AddMethodInfo,
Expression.Convert(CallNewGuidExpr, typeof(object)),
Expression.Constant(new Tuple<Type, Type>(requestedType, type), typeof(object))),
Expression.Rethrow(tryBlock.Type));
return new[] { Expression.TryCatch(tryBlock, Expression.Catch(ExceptionExpr, catchBlock))};
}
}
}

Просмотреть файл

@ -68,19 +68,6 @@ namespace Unity
$"Open generic method {member.Name} on type '{member.DeclaringType.Name}' is marked for injection. Open generic methods cannot be injected.", member);
}
var parameters = member.GetParameters();
if (parameters.Any(param => param.IsOut))
{
yield return new InvalidRegistrationException(
$"Method {member.Name} on type '{member.DeclaringType.Name}' is marked for injection. Methods with 'out' parameters cannot be injected.", member);
}
if (parameters.Any(param => param.ParameterType.IsByRef))
{
yield return new InvalidRegistrationException(
$"Method {member.Name} on type '{member.DeclaringType.Name}' has 'ref' parameter and cannot be injected.", member);
}
yield return member;
break;
}
@ -94,26 +81,21 @@ namespace Unity
protected override ResolveDelegate<PipelineContext> GetResolverDelegate(MethodInfo info, object? resolvers)
{
var parameterResolvers = ParameterResolvers(info.GetParameters(), resolvers).ToArray();
return (ref PipelineContext c) =>
var resolver = base.GetResolverDelegate(info, resolvers);
return (ref PipelineContext context) =>
{
try
{
if (null == c.Existing) return c.Existing;
// TODO: Add validation
var parameters = new object[parameterResolvers.Length];
for (var i = 0; i < parameters.Length; i++)
parameters[i] = parameterResolvers[i](ref c);
info.Invoke(c.Existing, parameters);
return resolver(ref context);
}
catch (Exception ex)
{
ex.Data.Add(Guid.NewGuid(), info);
throw;
}
return c.Existing;
};
}
#endregion