Invalid verify on a non-virtual on an interface - c#

The following code is raising and exception, MOQ is complaining about:
"Invalid verify on a non-virtual"
but I am mocking an interface. I must have done these sort of tests a good few times but I'm not being able to figure what the issue is this time.
[TestFixture]
public class RegisterDeviceCommandHandlerTests
{
private RegisterDeviceCommandHandler _handler;
private readonly Mock<IClientRepository> _clientRepositoryMock = new Mock<IClientRepository>();
private readonly Mock<IMessageHandlerContext> _busMock = new Mock<IMessageHandlerContext>();
private readonly Mock<IClientEncryptionProvider> _clientEncryptionProviderMock = new Mock<IClientEncryptionProvider>();
[Test]
public async Task GivenAnUnregisteredDeviceWhenTheDeviceIsAddedThenADeviceRegistrationCompletedEventShouldBePublished()
{
_clientRepositoryMock.Setup(x => x.RegisterClient(It.IsAny<byte[]>(), It.IsAny<string>(),
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Returns(RegistrationClientOperationResult.Registered);
var clientIdentity = new ClientIdentity
{
HostName = "HostName",
MacAddress = "MacAddress",
MachineId = "MachineId"
};
_clientEncryptionProviderMock.Setup(x => x.DecryptIdentity(It.IsAny<byte[]>())).Returns(clientIdentity);
_handler = new RegisterDeviceCommandHandler(_clientEncryptionProviderMock.Object, _clientRepositoryMock.Object)
{
Bus = _busMock.Object
};
await _handler.HandleAsync(new RegisterDeviceCommand
{
Identity = new byte[] { 1, 2 }
});
_busMock.Verify(x => x.Publish(It.IsAny<DeviceRegistrationCompletedEvent>()));
}
}

Found it. IMessageHandlerContext inherits from IPipelineContext which has a Publish method
/// <summary>
/// Publish the message to subscribers.
/// </summary>
/// <param name="message">The message to publish.</param>
/// <param name="options">The options for the publish.</param>
Task Publish(object message, PublishOptions options);
An extension method that takes one argument is available for the interface and that method.
/// <summary>
/// Publish the message to subscribers.
/// </summary>
/// <param name="context">The instance of <see cref="IPipelineContext" /> to use for the action.</param>
/// <param name="message">The message to publish.</param>
public static Task Publish(this IPipelineContext context, object message)
{
Guard.AgainstNull(nameof(context), context);
Guard.AgainstNull(nameof(message), message);
return context.Publish(message, new PublishOptions());
}
So to satisfy the extension method with the mock you would need to verify
_busMock.Verify(_ => _.Publish(It.IsAny<DeviceRegistrationCompletedEvent>(), Is.IsAny<PublishOptions>()));

Related

Confused about Autofac Middleware module

So I'm following an example of setting up LoggerMiddleware which is demonstrated here which I've adapted to just use .NET Core's ILogger. We already had a LoggerModule which work pre v6 so I copied the creation code into the LoggerMiddleware class to suit.
What I don't understand is how to register this. There's no default constructor on the Module so I can't use builder.RegisterModule<MiddlewareModule>(). I know I can pre-create the MiddlewareModule passing in an instance of the LoggerMiddleware then builder.RegisterModule(moduleInstance) but this MiddlewareModule is supposed to be used for all Middleware we create. This doco page doesn't elaborate on that final detail. Do I just do this per instance of IResolveMiddleware?:
var loggerMiddlewareModule = new MiddlewareModule(new LoggerMiddleware());
builder.RegisterModule(loggerMiddlewareModule);
var otherMiddlewareModule = new MiddlewareModule(new OtherMiddleware());
builder.RegisterModule(otherMiddlewareModule);
My Middleware and Module:
public class LoggerMiddleware : IResolveMiddleware
{
public PipelinePhase Phase => PipelinePhase.ParameterSelection;
public void Execute(ResolveRequestContext context, Action<ResolveRequestContext> next)
{
var t = context.Registration.Activator.LimitType;
// Add our parameters.
context.ChangeParameters(context.Parameters.Union(
new[]
{
new ResolvedParameter((p, i) => p.ParameterType == typeof(ILogger), (p, i) => GetLogger(i, t)),
new ResolvedParameter(
(p, i) => p.ParameterType.GenericTypeArguments.Any() &&
p.ParameterType.GetGenericTypeDefinition() == typeof(ILogger<>),
(p, i) => GetGenericTypeLogger(i, t))
}));
// Continue the resolve.
next(context);
// Has an instance been activated?
if (context.NewInstanceActivated)
{
var instanceType = context.Instance.GetType();
// Get all the injectable properties to set.
// If you wanted to ensure the properties were only UNSET properties,
// here's where you'd do it.
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILogger) && p.CanWrite && p.GetIndexParameters().Length == 0);
// Set the properties located.
foreach (var propToSet in properties)
{
propToSet.SetValue(context.Instance, GetLogger(context, instanceType), null);
}
}
}
/// <summary>
/// The log cache.
/// </summary>
private static readonly ConcurrentDictionary<Type, object> _logCache = new ConcurrentDictionary<Type, object>();
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="context">The component context.</param>
/// <param name="declaringType">The type of logger.</param>
/// <returns>The logger instance.</returns>
private static object GetGenericTypeLogger(IComponentContext context, Type declaringType)
{
return _logCache.GetOrAdd(
declaringType,
x =>
{
var wrapper = typeof(LoggerWrapper<>);
var specificWrapper = wrapper.MakeGenericType(declaringType);
var instance = (ILoggerWrapper)Activator.CreateInstance(specificWrapper);
var factory = context.Resolve<ILoggerFactory>();
return instance!.Create(factory);
});
}
/// <summary>
/// Gets the logger.
/// </summary>
/// <param name="context">The component context.</param>
/// <param name="declaringType">The type of logger.</param>
/// <returns>The logger instance.</returns>
private static object GetLogger(IComponentContext context, Type declaringType)
{
return _logCache.GetOrAdd(
declaringType,
x =>
{
var factory = context.Resolve<ILoggerFactory>();
return factory.CreateLogger(declaringType);
});
}
/// <summary>
/// The <see cref="ILoggerWrapper" />
/// interface defines the method for creating a generic type logger.
/// </summary>
private interface ILoggerWrapper
{
/// <summary>
/// Creates a generic type logger using the specified factory.
/// </summary>
/// <param name="factory">The factory.</param>
/// <returns>The logger.</returns>
object Create(ILoggerFactory factory);
}
private class LoggerWrapper<T> : ILoggerWrapper
{
public object Create(ILoggerFactory factory)
{
return factory.CreateLogger<T>();
}
}
}
public class MiddlewareModule : Module
{
private readonly IResolveMiddleware _middleware;
public MiddlewareModule(IResolveMiddleware middleware)
{
_middleware = middleware;
}
protected override void AttachToComponentRegistration(IComponentRegistryBuilder componentRegistry, IComponentRegistration registration)
{
// Attach to the registrations pipeline build
registration.PipelineBuilding += (sender, pipeline) =>
{
// Add our middleware to the pipeline
pipeline.Use(_middleware);
};
}
===============
Further question:
So when I run this I'm getting DependencyResolutionException and not quite sure where to look.
This is what the middleware module registration looks like:
There are other standard modules doing RegisterType and Register calls.
You've got it right; that example MiddlewareModule registers a single instance of an IResolveMiddleware in the pipeline of every registration, so you need one instance of the module for each different middleware you want to add.
You could equally have a custom Module that registers multiple middleware, or construct a different middleware instance per-registration; this was just an example.

How to build a dynamic command object?

I'll try to make this as clear as possible.
A Plugin architecture using reflection and 2 Attributes and an abstract class:
PluginEntryAttribute(Targets.Assembly, typeof(MyPlugin))
PluginImplAttribute(Targets.Class, ...)
abstract class Plugin
Commands are routed to a plugin via an interface and a delegate:
Ex: public delegate TTarget Command<TTarget>(object obj);
Using extension methods with Command<> as the target, a CommandRouter executes the delegate on the correct target interface:
Ex:
public static TResult Execute<TTarget, TResult>(this Command<TTarget> target, Func<TTarget, TResult> func) {
return CommandRouter.Default.Execute(func);
}
Putting this together, I have a class hard-coded with the command delegates like so:
public class Repositories {
public static Command<IDispatchingRepository> Dispatching = (o) => { return (IDispatchingRepository)o; };
public static Command<IPositioningRepository> Positioning = (o) => { return (IPositioningRepository)o; };
public static Command<ISchedulingRepository> Scheduling = (o) => { return (ISchedulingRepository)o; };
public static Command<IHistographyRepository> Histography = (o) => { return (IHistographyRepository)o; };
}
When an object wants to query from the repository, practical execution looks like this:
var expBob = Dispatching.Execute(repo => repo.AddCustomer("Bob"));
var actBob = Dispatching.Execute(repo => repo.GetCustomer("Bob"));
My question is this: how can I create such a class as Repositories dynamically from the plugins?
I can see the possibility that another attribute might be necessary. Something along the lines of:
[RoutedCommand("Dispatching", typeof(IDispatchingRepository)")]
public Command<IDispatchingRepository> Dispatching = (o) => { return (IDispatchingRepository)o; };
This is just an idea, but I'm at a loss as to how I'd still create a dynamic menu of sorts like the Repositories class.
For completeness, the CommandRouter.Execute(...) method and related Dictionary<,>:
private readonly Dictionary<Type, object> commandTargets;
internal TResult Execute<TTarget, TResult>(Func<TTarget, TResult> func) {
var result = default(TResult);
if (commandTargets.TryGetValue(typeof(TTarget), out object target)) {
result = func((TTarget)target);
}
return result;
}
OK, i am not sure if this is what you are looking for. I am assuming that each plugin contains field of the following definition:
public Command<T> {Name} = (o) => { return (T)o; };
example from code provided by you:
public Command<IDispatchingRepository> Dispatching = (o) => { return (IDispatchingRepository)o; };
One way to dynamically create class in .NET Core is by using the Microsoft.CodeAnalysis.CSharp nuget - this is Roslyn.
The result is compiled assembly with class called DynamicRepositories having all command fields from all plugins from all loaded dlls into the current AppDomain represented as static public fields.
The code has 3 main components: DynamicRepositoriesBuildInfo class, GetDynamicRepositoriesBuildInfo method and LoadDynamicRepositortyIntoAppDomain method.
DynamicRepositoriesBuildInfo - information for the command fields from the plugins and all assemblies needed to be loaded during the dynamic complication. This will be the assemblies which defines the Command type and the generic arguments of the Command type (ex: IDispatchingRepository)
GetDynamicRepositoriesBuildInfo method - creates DynamicRepositoriesBuildInfo using reflection by scanning loaded assemblies for the PluginEntryAttribute and PluginImplAttribute.
LoadDynamicRepositortyIntoAppDomain method - DynamicRepositoriesBuildInfo it creates assembly called DynamicRepository.dll with single public class App.Dynamic.DynamicRepositories
Here is the code
public class DynamicRepositoriesBuildInfo
{
public IReadOnlyCollection<Assembly> ReferencesAssemblies { get; }
public IReadOnlyCollection<FieldInfo> PluginCommandFieldInfos { get; }
public DynamicRepositoriesBuildInfo(
IReadOnlyCollection<Assembly> referencesAssemblies,
IReadOnlyCollection<FieldInfo> pluginCommandFieldInfos)
{
this.ReferencesAssemblies = referencesAssemblies;
this.PluginCommandFieldInfos = pluginCommandFieldInfos;
}
}
private static DynamicRepositoriesBuildInfo GetDynamicRepositoriesBuildInfo()
{
var pluginCommandProperties = (from a in AppDomain.CurrentDomain.GetAssemblies()
let entryAttr = a.GetCustomAttribute<PluginEntryAttribute>()
where entryAttr != null
from t in a.DefinedTypes
where t == entryAttr.PluginType
from p in t.GetFields(BindingFlags.Public | BindingFlags.Instance)
where p.FieldType.GetGenericTypeDefinition() == typeof(Command<>)
select p).ToList();
var referenceAssemblies = pluginCommandProperties
.Select(x => x.DeclaringType.Assembly)
.ToList();
referenceAssemblies.AddRange(
pluginCommandProperties
.SelectMany(x => x.FieldType.GetGenericArguments())
.Select(x => x.Assembly)
);
var buildInfo = new DynamicRepositoriesBuildInfo(
pluginCommandFieldInfos: pluginCommandProperties,
referencesAssemblies: referenceAssemblies.Distinct().ToList()
);
return buildInfo;
}
private static Assembly LoadDynamicRepositortyIntoAppDomain()
{
var buildInfo = GetDynamicRepositoriesBuildInfo();
var csScriptBuilder = new StringBuilder();
csScriptBuilder.AppendLine("using System;");
csScriptBuilder.AppendLine("namespace App.Dynamic");
csScriptBuilder.AppendLine("{");
csScriptBuilder.AppendLine(" public class DynamicRepositories");
csScriptBuilder.AppendLine(" {");
foreach (var commandFieldInfo in buildInfo.PluginCommandFieldInfos)
{
var commandNamespaceStr = commandFieldInfo.FieldType.Namespace;
var commandTypeStr = commandFieldInfo.FieldType.Name.Split('`')[0];
var commandGenericArgStr = commandFieldInfo.FieldType.GetGenericArguments().Single().FullName;
var commandFieldNameStr = commandFieldInfo.Name;
csScriptBuilder.AppendLine($"public {commandNamespaceStr}.{commandTypeStr}<{commandGenericArgStr}> {commandFieldNameStr} => (o) => ({commandGenericArgStr})o;");
}
csScriptBuilder.AppendLine(" }");
csScriptBuilder.AppendLine("}");
var sourceText = SourceText.From(csScriptBuilder.ToString());
var parseOpt = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_3);
var syntaxTree = SyntaxFactory.ParseSyntaxTree(sourceText, parseOpt);
var references = new List<MetadataReference>
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(System.Runtime.AssemblyTargetedPatchBandAttribute).Assembly.Location),
};
references.AddRange(buildInfo.ReferencesAssemblies.Select(a => MetadataReference.CreateFromFile(a.Location)));
var compileOpt = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
optimizationLevel: OptimizationLevel.Release,
assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default);
var compilation = CSharpCompilation.Create(
"DynamicRepository.dll",
new[] { syntaxTree },
references: references,
options: compileOpt);
using (var memStream = new MemoryStream())
{
var result = compilation.Emit(memStream);
if (result.Success)
{
var assembly = AppDomain.CurrentDomain.Load(memStream.ToArray());
return assembly;
}
else
{
throw new ArgumentException();
}
}
}
This is how to execute the code
var assembly = LoadDynamicRepositortyIntoAppDomain();
var type = assembly.GetType("App.Dynamic.DynamicRepositories");
The type variable represents the compiled class which has all the plugin commands as public static fields. You are loosing all type safety once you start using dynamic code compilation / building. If you need to execute some code from the type variable you will need reflection.
So if you have
PluginA
{
public Command<IDispatchingRepository> Dispatching= (o) => ....
}
PluginB
{
public Command<IDispatchingRepository> Scheduling = (o) => ....
}
the dynamically create type will look like this
public class DynamicRepositories
{
public static Command<IDispatchingRepository> Dispatching= (o) => ....
public static Command<IDispatchingRepository> Scheduling = (o) => ....
}
Here's another take, which does not require building code dynamically.
I'm assuming the following code for the plugin framework. Note that I did not make any assumptions regarding the abstract Plugin class, because I had no further information.
#region Plugin Framework
public delegate TTarget Command<out TTarget>(object obj);
/// <summary>
/// Abstract base class for plugins.
/// </summary>
public abstract class Plugin
{
}
#endregion
Next, here are two sample plugins. Note the DynamicTarget custom attributes, which I will describe in the next step.
#region Sample Plugin: ICustomerRepository
/// <summary>
/// Sample model class, representing a customer.
/// </summary>
public class Customer
{
public Customer(string name)
{
Name = name;
}
public string Name { get; }
}
/// <summary>
/// Sample target interface.
/// </summary>
public interface ICustomerRepository
{
Customer AddCustomer(string name);
Customer GetCustomer(string name);
}
/// <summary>
/// Sample plugin.
/// </summary>
[DynamicTarget(typeof(ICustomerRepository))]
public class CustomerRepositoryPlugin : Plugin, ICustomerRepository
{
private readonly Dictionary<string, Customer> _customers = new Dictionary<string, Customer>();
public Customer AddCustomer(string name)
{
var customer = new Customer(name);
_customers[name] = customer;
return customer;
}
public Customer GetCustomer(string name)
{
return _customers[name];
}
}
#endregion
#region Sample Plugin: IProductRepository
/// <summary>
/// Sample model class, representing a product.
/// </summary>
public class Product
{
public Product(string name)
{
Name = name;
}
public string Name { get; }
}
/// <summary>
/// Sample target interface.
/// </summary>
public interface IProductRepository
{
Product AddProduct(string name);
Product GetProduct(string name);
}
/// <summary>
/// Sample plugin.
/// </summary>
[DynamicTarget(typeof(IProductRepository))]
public class ProductRepositoryPlugin : Plugin, IProductRepository
{
private readonly Dictionary<string, Product> _products = new Dictionary<string, Product>();
public Product AddProduct(string name)
{
var product = new Product(name);
_products[name] = product;
return product;
}
public Product GetProduct(string name)
{
return _products[name];
}
}
#endregion
Here's what your static Repositories class would look like with the two sample plugins:
#region Static Repositories Example Class from Question
public static class Repositories
{
public static readonly Command<ICustomerRepository> CustomerRepositoryCommand = o => (ICustomerRepository) o;
public static readonly Command<IProductRepository> ProductRepositoryCommand = o => (IProductRepository) o;
}
#endregion
To begin the actual answer to your question here's the custom attribute used to mark the plugins. This custom attribute has been used on the two example plugins shown above.
/// <summary>
/// Marks a plugin as the target of a <see cref="Command{TTarget}" />, specifying
/// the type to be registered with the <see cref="DynamicCommands" />.
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public class DynamicTargetAttribute : Attribute
{
public DynamicTargetAttribute(Type type)
{
Type = type;
}
public Type Type { get; }
}
The custom attribute is parsed in the RegisterDynamicTargets(Assembly) of the following DynamicRepository class to identify the plugins and the types (e.g., ICustomerRepository) to be registered. The targets are registered with the CommandRouter shown below.
/// <summary>
/// A dynamic command repository.
/// </summary>
public static class DynamicCommands
{
/// <summary>
/// For all assemblies in the current domain, registers all targets marked with the
/// <see cref="DynamicTargetAttribute" />.
/// </summary>
public static void RegisterDynamicTargets()
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
RegisterDynamicTargets(assembly);
}
}
/// <summary>
/// For the given <see cref="Assembly" />, registers all targets marked with the
/// <see cref="DynamicTargetAttribute" />.
/// </summary>
/// <param name="assembly"></param>
public static void RegisterDynamicTargets(Assembly assembly)
{
IEnumerable<Type> types = assembly
.GetTypes()
.Where(type => type.CustomAttributes
.Any(ca => ca.AttributeType == typeof(DynamicTargetAttribute)));
foreach (Type type in types)
{
// Note: This assumes that we simply instantiate an instance upon registration.
// You might have a different convention with your plugins (e.g., they might be
// singletons accessed via an Instance or Default property). Therefore, you
// might have to change this.
object target = Activator.CreateInstance(type);
IEnumerable<CustomAttributeData> customAttributes = type.CustomAttributes
.Where(ca => ca.AttributeType == typeof(DynamicTargetAttribute));
foreach (CustomAttributeData customAttribute in customAttributes)
{
CustomAttributeTypedArgument argument = customAttribute.ConstructorArguments.First();
CommandRouter.Default.RegisterTarget((Type) argument.Value, target);
}
}
}
/// <summary>
/// Registers the given target.
/// </summary>
/// <typeparam name="TTarget">The type of the target.</typeparam>
/// <param name="target">The target.</param>
public static void RegisterTarget<TTarget>(TTarget target)
{
CommandRouter.Default.RegisterTarget(target);
}
/// <summary>
/// Gets the <see cref="Command{TTarget}" /> for the given <typeparamref name="TTarget" />
/// type.
/// </summary>
/// <typeparam name="TTarget">The target type.</typeparam>
/// <returns>The <see cref="Command{TTarget}" />.</returns>
public static Command<TTarget> Get<TTarget>()
{
return obj => (TTarget) obj;
}
/// <summary>
/// Extension method used to help dispatch the command.
/// </summary>
/// <typeparam name="TTarget">The type of the target.</typeparam>
/// <typeparam name="TResult">The type of the result of the function invoked on the target.</typeparam>
/// <param name="_">The <see cref="Command{TTarget}" />.</param>
/// <param name="func">The function invoked on the target.</param>
/// <returns>The result of the function invoked on the target.</returns>
public static TResult Execute<TTarget, TResult>(this Command<TTarget> _, Func<TTarget, TResult> func)
{
return CommandRouter.Default.Execute(func);
}
}
Instead of dynamically creating properties, the above utility class offers a simple Command<TTarget> Get<TTarget>() method, with which you can create the Command<TTarget> instance, which is then used in the Execute extension method. The latter method finally delegates to the CommandRouter shown next.
/// <summary>
/// Command router used to dispatch commands to targets.
/// </summary>
public class CommandRouter
{
public static readonly CommandRouter Default = new CommandRouter();
private readonly Dictionary<Type, object> _commandTargets = new Dictionary<Type, object>();
/// <summary>
/// Registers a target.
/// </summary>
/// <typeparam name="TTarget">The type of the target instance.</typeparam>
/// <param name="target">The target instance.</param>
public void RegisterTarget<TTarget>(TTarget target)
{
_commandTargets[typeof(TTarget)] = target;
}
/// <summary>
/// Registers a target instance by <see cref="Type" />.
/// </summary>
/// <param name="type">The <see cref="Type" /> of the target.</param>
/// <param name="target">The target instance.</param>
public void RegisterTarget(Type type, object target)
{
_commandTargets[type] = target;
}
internal TResult Execute<TTarget, TResult>(Func<TTarget, TResult> func)
{
var result = default(TResult);
if (_commandTargets.TryGetValue(typeof(TTarget), out object target))
{
result = func((TTarget)target);
}
return result;
}
}
#endregion
Finally, here are a few unit tests showing how the above classes work.
#region Unit Tests
public class DynamicCommandTests
{
[Fact]
public void TestUsingStaticRepository_StaticDeclaration_Success()
{
ICustomerRepository customerRepository = new CustomerRepositoryPlugin();
CommandRouter.Default.RegisterTarget(customerRepository);
Command<ICustomerRepository> command = Repositories.CustomerRepositoryCommand;
Customer expected = command.Execute(repo => repo.AddCustomer("Bob"));
Customer actual = command.Execute(repo => repo.GetCustomer("Bob"));
Assert.Equal(expected, actual);
Assert.Equal("Bob", actual.Name);
}
[Fact]
public void TestUsingDynamicRepository_ManualRegistration_Success()
{
ICustomerRepository customerRepository = new CustomerRepositoryPlugin();
DynamicCommands.RegisterTarget(customerRepository);
Command<ICustomerRepository> command = DynamicCommands.Get<ICustomerRepository>();
Customer expected = command.Execute(repo => repo.AddCustomer("Bob"));
Customer actual = command.Execute(repo => repo.GetCustomer("Bob"));
Assert.Equal(expected, actual);
Assert.Equal("Bob", actual.Name);
}
[Fact]
public void TestUsingDynamicRepository_DynamicRegistration_Success()
{
// Register all plugins, i.e., CustomerRepositoryPlugin and ProductRepositoryPlugin
// in this test case.
DynamicCommands.RegisterDynamicTargets();
// Invoke ICustomerRepository methods on CustomerRepositoryPlugin target.
Command<ICustomerRepository> customerCommand = DynamicCommands.Get<ICustomerRepository>();
Customer expectedBob = customerCommand.Execute(repo => repo.AddCustomer("Bob"));
Customer actualBob = customerCommand.Execute(repo => repo.GetCustomer("Bob"));
Assert.Equal(expectedBob, actualBob);
Assert.Equal("Bob", actualBob.Name);
// Invoke IProductRepository methods on ProductRepositoryPlugin target.
Command<IProductRepository> productCommand = DynamicCommands.Get<IProductRepository>();
Product expectedHammer = productCommand.Execute(repo => repo.AddProduct("Hammer"));
Product actualHammer = productCommand.Execute(repo => repo.GetProduct("Hammer"));
Assert.Equal(expectedHammer, actualHammer);
Assert.Equal("Hammer", actualHammer.Name);
}
}
#endregion
You can find the whole implementation here.

Use MiniProfiler to capture slow requests

I want to use MiniProfiler to call a function once a set time limit has gone by. This is how MiniProfiler is set up. After that I've included the profiling script which we use to profile whatever needs profiling. My problem is to create some sort of middleware that can intercept this "MiniProfiler.Current.Step" call when the timing is greater than 1000ms.
app.UseMiniProfiler(new MiniProfilerOptions
{
ResultsAuthorize = x => false,
ResultsListAuthorize = x => false,
Storage = new SqlServerStorage(Configuration.GetConnectionString("MiniProfiler"))
});
MiniProfilerEF6.Initialize();
app.Use(async (context, next) =>
{
MiniProfiler.Current.Name = context.Request.GetDisplayUrl();
await next.Invoke();
});
/// <summary>
/// The main profiler, useage:
/// using(this.Profile("more context"))
/// {
/// Do things that needs profiling, and you may nest it.
/// }
/// </summary>
/// <param name="profiled">The object that is profiled</param>
/// <param name="subSectionName">More context for the output result</param>
/// <param name="methodName">Possible override for the method name called</param>
/// <param name="profiledTypeName">Possible override for the profiled type</param>
/// <returns>An IDisposable, to help with scoping</returns>
public static IDisposable Profile(this object profiled,
string subSectionName = null,
[CallerMemberName] string methodName = "",
string profiledTypeName = null)
{
if (profiled == null)
throw new ArgumentNullException(nameof(profiled));
var profiledType = profiledTypeName ?? profiled.GetType().Name;
return Profile(methodName, profiledType, subSectionName);
}
public static IDisposable Profile(string methodName,
string profiledTypeName,
string subSectionName = null)
{
var name = subSectionName != null
? $"{profiledTypeName}.{methodName}:{subSectionName}"
: $"{profiledTypeName}.{methodName}";
return MiniProfiler.Current?.Step(name);
}

How to wait until item goes through pipeline?

So, I'm trying to wrap my head around Microsoft's Dataflow library. I've built a very simple pipeline consisting of just two blocks:
var start = new TransformBlock<Foo, Bar>();
var end = new ActionBlock<Bar>();
start.LinkTo(end);
Now I can asynchronously process Foo instances by calling:
start.SendAsync(new Foo());
What I do not understand is how to do the processing synchronously, when needed. I thought that waiting on SendAsync would be enough:
start.SendAsync(new Foo()).Wait();
But apparently it returns as soon as item is accepted by first processor in pipeline, and not when item is fully processed. So is there a way to wait until given item was processed by last (end) block? Apart from passing a WaitHandle through entire pipeline.
In short that's not supported out of the box in data flow. Essentially what you need to do is to tag the data so you can retrieve it when processing is done. I've written up a way to do this that let's the consumer await a Job as it gets processed by the pipeline. The only concession to pipeline design is that each block take a KeyValuePair<Guid, T>. This is the basic JobManager and the post I wrote about it. Note the code in the post is a bit dated and needs some updates but it should get you in the right direction.
namespace ConcurrentFlows.DataflowJobs {
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
/// <summary>
/// A generic interface defining that:
/// for a specified input type => an awaitable result is produced.
/// </summary>
/// <typeparam name="TInput">The type of data to process.</typeparam>
/// <typeparam name="TOutput">The type of data the consumer expects back.</typeparam>
public interface IJobManager<TInput, TOutput> {
Task<TOutput> SubmitRequest(TInput data);
}
/// <summary>
/// A TPL-Dataflow based job manager.
/// </summary>
/// <typeparam name="TInput">The type of data to process.</typeparam>
/// <typeparam name="TOutput">The type of data the consumer expects back.</typeparam>
public class DataflowJobManager<TInput, TOutput> : IJobManager<TInput, TOutput> {
/// <summary>
/// It is anticipated that jobHandler is an injected
/// singleton instance of a Dataflow based 'calculator', though this implementation
/// does not depend on it being a singleton.
/// </summary>
/// <param name="jobHandler">A singleton Dataflow block through which all jobs are processed.</param>
public DataflowJobManager(IPropagatorBlock<KeyValuePair<Guid, TInput>, KeyValuePair<Guid, TOutput>> jobHandler) {
if (jobHandler == null) { throw new ArgumentException("Argument cannot be null.", "jobHandler"); }
this.JobHandler = JobHandler;
if (!alreadyLinked) {
JobHandler.LinkTo(ResultHandler, new DataflowLinkOptions() { PropagateCompletion = true });
alreadyLinked = true;
}
}
private static bool alreadyLinked = false;
/// <summary>
/// Submits the request to the JobHandler and asynchronously awaits the result.
/// </summary>
/// <param name="data">The input data to be processd.</param>
/// <returns></returns>
public async Task<TOutput> SubmitRequest(TInput data) {
var taggedData = TagInputData(data);
var job = CreateJob(taggedData);
Jobs.TryAdd(job.Key, job.Value);
await JobHandler.SendAsync(taggedData);
return await job.Value.Task;
}
private static ConcurrentDictionary<Guid, TaskCompletionSource<TOutput>> Jobs {
get;
} = new ConcurrentDictionary<Guid, TaskCompletionSource<TOutput>>();
private static ExecutionDataflowBlockOptions Options {
get;
} = GetResultHandlerOptions();
private static ITargetBlock<KeyValuePair<Guid, TOutput>> ResultHandler {
get;
} = CreateReplyHandler(Options);
private IPropagatorBlock<KeyValuePair<Guid, TInput>, KeyValuePair<Guid, TOutput>> JobHandler {
get;
}
private KeyValuePair<Guid, TInput> TagInputData(TInput data) {
var id = Guid.NewGuid();
return new KeyValuePair<Guid, TInput>(id, data);
}
private KeyValuePair<Guid, TaskCompletionSource<TOutput>> CreateJob(KeyValuePair<Guid, TInput> taggedData) {
var id = taggedData.Key;
var jobCompletionSource = new TaskCompletionSource<TOutput>();
return new KeyValuePair<Guid, TaskCompletionSource<TOutput>>(id, jobCompletionSource);
}
private static ExecutionDataflowBlockOptions GetResultHandlerOptions() {
return new ExecutionDataflowBlockOptions() {
MaxDegreeOfParallelism = Environment.ProcessorCount,
BoundedCapacity = 1000
};
}
private static ITargetBlock<KeyValuePair<Guid, TOutput>> CreateReplyHandler(ExecutionDataflowBlockOptions options) {
return new ActionBlock<KeyValuePair<Guid, TOutput>>((result) => {
RecieveOutput(result);
}, options);
}
private static void RecieveOutput(KeyValuePair<Guid, TOutput> result) {
var jobId = result.Key;
TaskCompletionSource<TOutput> jobCompletionSource;
if (!Jobs.TryRemove(jobId, out jobCompletionSource)) {
throw new InvalidOperationException($"The jobId: {jobId} was not found.");
}
var resultValue = result.Value;
jobCompletionSource.SetResult(resultValue);
}
}
}
I ended up using the following pipeline:
var start = new TransformBlock<FooBar, FooBar>(...);
var end = new ActionBlock<FooBar>(item => item.Complete());
start.LinkTo(end);
var input = new FooBar {Input = new Foo()};
start.SendAsync(input);
input.Task.Wait();
Where
class FooBar
{
public Foo Input { get; set; }
public Bar Result { get; set; }
public Task<Bar> Task { get { return _taskSource.Task; } }
public void Complete()
{
_taskSource.SetResult(Result);
}
private TaskCompletionSource<Bar> _taskSource = new TaskCompletionSource<Bar>();
}
Less than ideal, but it works.

Is there a newer way to accomplish what this article recommends?

I like the idea of this Agent Service that allows me to add jobs without affecting existing code, but the article is pretty old. Has something come along since 2005 that would be a better way of accomplishing the same thing?
I am limited to .Net, but I can use any version of the framework.
http://visualstudiomagazine.com/articles/2005/05/01/create-a-net-agent.aspx
Edit: Here is a summary of what I'm trying to do
Have a .Net service that can read a configuration file to dynamically load DLLs to perform tasks.
The service has a dynamic object loader that maps XML to classes in the DLLs to perform the tasks.
An example of the xml file and the class it maps is below. Basically, the service can read the Job from the xml, instantiate an instance of the CustomerAttendeeCreateNotificationWorker and call the Run() method. As a developer, I can make any number of these classes and implement whatever I want in the Run() method. Also note that the entry for "CustomerAttendanceNotificationTemplateName" gets assigned to a property with the same name on the instantiated object.
<?xml version="1.0" encoding="utf-8"?>
<Manager type="Task.RemotingManager, TaskClasses">
<Jobs type="Task.TaskJob, TaskBase" Name="CustomerAttendeeCreateNotificationWorker Worker">
<Worker type="TaskWorkers.CustomerAttendeeCreateNotificationWorker, TaskWorkers"
Description="Inserts records into NotificationQueue for CustomerAttendees"
CustomerAttendanceNotificationTemplateName ="CustomerAttendanceNotificationTemplateName"
/>
<Schedulers type="Task.FixedIntervalScheduler, TaskClasses"
DaysOfWeek="Everyday"
Frequency="00:05:00"
StartTime="00:00:00"
EndTime="23:55:00"
/>
</Jobs>
<Jobs type="Task.TaskJob, TaskBase" Name="SendNotificationWorker Worker">
<Worker type="TaskWorkers.SendNotificationWorker, TaskWorkers"
Description="Sends messages from NotificationQueue"
/>
<Schedulers type="Task.FixedIntervalScheduler, TaskClasses"
DaysOfWeek="Everyday"
Frequency="00:05:00"
StartTime="00:00:00"
EndTime="23:55:00"
/>
</Jobs>/>
</Manager>
/// <summary>
/// The customer attendee create notification worker.
/// </summary>
[Serializable]
public class CustomerAttendeeCreateNotificationWorker : TaskWorker
{
#region Constants
/// <summary>
/// The stat e_ critical.
/// </summary>
private const int StateCritical = 1;
/// <summary>
/// The stat e_ ok.
/// </summary>
private const int StateOk = 0;
#endregion
#region Fields
/// <summary>
/// The customer notification setting name.
/// </summary>
private string customerAttendanceNotificationTemplateName;
#endregion
#region Public Properties
/// <summary>
/// The customer notification setting name.
/// </summary>
public string CustomerAttendanceNotificationTemplateName
{
get
{
return this.customerAttendanceNotificationTemplateName;
}
set
{
this.customerAttendanceNotificationTemplateName = value;
}
}
/// <summary>
/// Gets or sets the logger.
/// </summary>
public ILogger Logger { get; set; }
#endregion
#region Public Methods and Operators
/// <summary>
/// The run.
/// </summary>
/// <returns>
/// The <see cref="TaskResult" />.
/// </returns>
public override TaskResult Run()
{
StringBuilder errorStringBuilder = new StringBuilder();
string errorLineTemplate = "Time: {0} Database: {1} Error Message: {2}" + Environment.NewLine;
bool isError = false;
IUnitOfWork configUnitOfWork = new GenericUnitOfWork<DCCShowConfigContext>();
TradeshowService tradeshowService = new TradeshowService(configUnitOfWork);
List<Tradeshow> tradeshows = tradeshowService.GetAll().Where(t => t.Status == "OPEN").ToList();
string connectionStringTemplate = ConfigurationManager.ConnectionStrings["DCCTradeshow"].ConnectionString;
int customerNotificationSettingGroupId = Convert.ToInt32(ConfigurationManager.AppSettings["NotificationSettingGroupId"]);
foreach (Tradeshow tradeshow in tradeshows)
{
try
{
string connectionString = string.Format(connectionStringTemplate, tradeshow.DbName);
IUnitOfWork unitOfWork = new TradeshowUnitOfWork(connectionString);
NotificationService notificationService = new NotificationService(unitOfWork);
notificationService.InsertCustomerAttendanceNotifications(tradeshow.TradeshowId, customerNotificationSettingGroupId, this.customerAttendanceNotificationTemplateName);
}
catch (Exception exception)
{
isError = true;
errorStringBuilder.AppendLine(string.Format(errorLineTemplate, DateTime.Now, tradeshow.DbName, exception.Message));
}
}
TaskResult result;
if (isError)
{
result = new TaskResult(StateOk, TaskResultStatus.Exception, "Errors Occured", errorStringBuilder.ToString());
}
else
{
result = new TaskResult(StateOk, TaskResultStatus.Ok,"All Good", "All Good");
}
return result;
}
#endregion
}`

Categories

Resources