Finished compiled pipeline
This commit is contained in:
Родитель
fb6139d6e9
Коммит
ff04af20dd
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче