Registering and resolving dependencies in a loop - dryioc

I have the following hardcoded setup in an application using MVVM:
var ips = configFile.Read();
for (string ip in ips)
{
var tcpClient = new TcpClient(ip);
var stream = (Stream) tcpClient.GetStream();
var service = new Service(stream);
var connectionViewModel = new ConnectionViewModel(service);
var extendedViewModel = new ExtendedViewModel(connectionViewModel);
}
A number of IP addresses are read from a file, and each address results in a ViewModel being created that displays stuff from the IP.
What is the best approach if I want to let DryIoc handle this? All new objects are unique foreach loop.

Possible option is using Func to pass the ip:
var c = new Container();
c.Register<ExtendedViewModel>();
c.Register<ConnectionViewModel>();
c.Register<Service>();
c.Register<TcpClient>();
foreach (var ip in ips) {
var getVM = c.Resolve<Func<string, ExtendedViewModel>>();
var vm = getVM(ip);
// use vm
}
Update:
For Stream, add the following registration without changing the resolution part:
c.Register<Stream>(Made.Of(
_ => ServiceInfo.Of<TcpClient>(),
tcpClient => (Stream)tcpClient.GetStream()));
Made.Of plays nicely with Func and other wrappers resolutions, and can be in the middle of object graph. That's why it is preferable over RegisterDelegate.

Related

Test not passing when db context n separate using blocks

I trying to do in memory ef core testing.
I have something similar to this:
Startup
services.AddEntityFrameworkNpgsql().AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("PostgresConnection"), x=>x.UseNetTopologySuite()))
.BuildServiceProvider();
Test method
public void Add_writes_to_database()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "Add_writes_to_database")
.Options;
// Run the test against one instance of the context
using (var context = new ApplicationDbContext(options))
{
var service = new BlogService(context);
service.Add("http://sample.com");
}
// Use a separate instance of the context to verify correct data was saved to database
using (var context = new ApplicationDbContext(options))
{
Assert.AreEqual(1, context.Blogs.Count());
Assert.AreEqual("http://sample.com", context.Blogs.Single().Url);
}
}
When the context is split into 2 using blocks like above it does not pass the test.
But when its all wrapped in one context it works ok.
Any ideas?
Had to also iclude InMemoryDatabaseRoot
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString(),
databaseRoot: new InMemoryDatabaseRoot())
.Options;

How do you replace one syntax token with multiple ones?

I've written an analyzer to force a library to use GetAwaiter().GetResult() instead of blocking a thread with .Result / .Wait()
After several hours and attempts to find a way to generate a syntaxtree which covers all my test cases i attempted to use the ReplaceToken method.
SyntaxNodeExtensions.cs
public static TRoot ReplaceToken<TRoot>(this TRoot root, SyntaxToken tokenInList, IEnumerable<SyntaxToken> newTokens) where TRoot : SyntaxNode
{
return (TRoot) root.ReplaceTokenInListCore(tokenInList, newTokens);
}
seemed like the perfect method - however i never got it working using this method.
I ended up doing it this way (which to me, seems rather lazy):
My working codefix
private async Task<Document> ReplaceWithGetAwaiterGetResultAsync(Document document, IdentifierNameSyntax declaration, CancellationToken cancellationToken)
{
var source = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
if(declaration.Identifier.ValueText == "Result")
return document.WithText(source.Replace(declaration.Span, "GetAwaiter().GetResult()"));
if(declaration.Identifier.ValueText == "Wait")
return document.WithText(source.Replace(new TextSpan(declaration.SpanStart, 6), "GetAwaiter().GetResult()"));
return document;
}
Does anyone know a better way of how i could have turned something like
Task.Run(() => 42).Result
into
Task.Run(() => 42).GetAwaiter.GetResult()
?
E.g. a version of this:
var tokens = SyntaxFactory.ParseTokens("GetAwaiter().GetResult()");
var root = await document.GetSyntaxRootAsync(cancellationToken);
var replaced = root.ReplaceToken(declaration.Identifier, tokens);
return document.WithSyntaxRoot(replaced.WithAdditionalAnnotations());
which does not crash.
The problem you faced when implementing your solution was that you tried to replace tokens. The access of the Result Property is however not a Token but a SyntaxNode.
The structure of your code consists of a MemberAccessExpression (Task.Run().Result) containing a MethodInvocationExpression (Task.Run()).
What you're trying to achieve is to remove the MemberAccessExpression, create a new MethodInvocationExpression (invocating GetAwaiter()) and insert the original InvocationExpression into your new Expression in order to call GetAwaiter() on the original expression.
Then you need to create another Incovation Expression to call GetResult().
To do this you need to create a new node like this and replace the old node using the SyntaxRoot:
private async Task<Document> ReplaceWithAwaiter(Document document,
IdentifierNameSyntax nameSyntax, CancellationToken cancellationToken)
{
var memberAccess = nameSyntax.Ancestors().OfType<MemberAccessExpressionSyntax>()
.First();
// Create .GetAwaiter()
var invocationOfAwaiter = SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
memberAccess.Expression, SyntaxFactory.IdentifierName("GetAwaiter")));
// Create .GetResult()
var invocationOfGetResult = SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
invocationOfAwaiter, SyntaxFactory.IdentifierName("GetResult")));
// Replace .Result by .GetAwaiter().GetResult()
var syntaxRoot = await document.GetSyntaxRootAsync();
syntaxRoot = syntaxRoot.ReplaceNode(memberAccess, invocationOfGetResult);
return document.WithSyntaxRoot(syntaxRoot);
}
For .Wait() the code is a bit different, but the same principle applies. In this case you want to replace an InvocationExpression instead of a MemberAccessExpression however.
private async Task<Document> ReplaceWithAwaiterForWait(Document document,
IdentifierNameSyntax nameSyntax, CancellationToken cancellationToken)
{
// Get the Invocation Task.Run().Wait()
var invocationOfWait = nameSyntax.Ancestors().OfType<InvocationExpressionSyntax>()
.First();
// Get the Access for Task.Run().Wait
var memberAccessOfWait = (MemberAccessExpressionSyntax)invocationOfWait.Expression;
// Get the Invocation Task.Run()
var invocationOfTaskRun = memberAccessOfWait.Expression;
// Create new Expressions
var invocationOfAwaiter = SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
invocationOfTaskRun, SyntaxFactory.IdentifierName("GetAwaiter")));
var invocationOfGetResult = SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
invocationOfAwaiter, SyntaxFactory.IdentifierName("GetResult")));
var syntaxRoot = await document.GetSyntaxRootAsync();
// Replace the old expression
syntaxRoot = syntaxRoot.ReplaceNode(invocationOfWait, invocationOfGetResult);
return document.WithSyntaxRoot(syntaxRoot);
}
If you don't wont to work with the generation of individual nodes you could also just use SyntaxFactory.ParseExpression() to generate a new expression and replace the old one:
private async Task<Document> ReplaceWithAwaiterWithParse(Document document,
IdentifierNameSyntax nameSyntax, CancellationToken cancellationToken)
{
var invocationOfWait = nameSyntax.Ancestors().OfType<InvocationExpressionSyntax>()
.First();
var memberAccessOfWait = (MemberAccessExpressionSyntax)invocationOfWait.Expression;
var invocationOfBoth = SyntaxFactory.ParseExpression(
memberAccessOfWait.Expression.ToFullString()
+ ".GetAwaiter().GetResult()");
var syntaxRoot = await document.GetSyntaxRootAsync();
syntaxRoot = syntaxRoot.ReplaceNode(invocationOfWait, invocationOfBoth);
return document.WithSyntaxRoot(syntaxRoot);
}
While this solution is a little shorter and more concise you would not be working on a string instead of the SyntaxTree which could create all kinds of issues. Furthermore the performance is a bit worse than using the SyntaxFactory to create individual objects. However you do not have to create every part of the invocation yourself.

How to write test using xUnit for service layer?

How do I write a test using xUnit for a service layer? I'm using dependency injection for my service layer, but how can I make an instance of it using an in memory database?
Here is what I got so far: I follow this link and here is what I came up to use my service layer, but it was a mess and I don't know how to simplify it. I am using an interface of the service in all of my controllers.
[Fact]
public void Add_writes_to_database()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "Add_writes_to_database")
.Options;
// Run the test against one instance of the context
using (var context = new ApplicationDbContext(options))
{
var productRepo = new Repository<Product>(context);
var categoryRepo = new Repository<Category>(context);
var categoryMappingRepo = new Repository<ProductCategoryMapping>(context);
var categoryService = new CategoryService(context, categoryRepo, categoryMappingRepo);
var manufacturerRepo = new Repository<Manufacturer>(context);
var manufacturerMappingRepo = new Repository<ProductManufacturerMapping>(context);
var manufacturerService = new ManufacturerService(context, manufacturerRepo, manufacturerMappingRepo);
var imageRepo = new Repository<Image>(context);
var imageMappingRepo = new Repository<ProductImageMapping>(context);
var imageService = new ImageManagerService(imageRepo, imageMappingRepo);
var specificationRepo = new Repository<Specification>(context);
var specificationMappingRepo = new Repository<ProductSpecificationMapping>(context);
var specificationService = new SpecificationService(context, specificationRepo, specificationMappingRepo);
var productService = new ProductService(context, productRepo, categoryService, manufacturerService, imageService, specificationService);
var product = new Product() { Id = Guid.NewGuid(), Name = "Product1", Price = 100m };
productService.InsertProduct(product);
}
// Use a separate instance of the context to verify correct data was saved to database
using (var context = new ApplicationDbContext(options))
{
var productRepo = new Repository<Product>(context);
var categoryRepo = new Repository<Category>(context);
var categoryMappingRepo = new Repository<ProductCategoryMapping>(context);
var categoryService = new CategoryService(context, categoryRepo, categoryMappingRepo);
var manufacturerRepo = new Repository<Manufacturer>(context);
var manufacturerMappingRepo = new Repository<ProductManufacturerMapping>(context);
var manufacturerService = new ManufacturerService(context, manufacturerRepo, manufacturerMappingRepo);
var imageRepo = new Repository<Image>(context);
var imageMappingRepo = new Repository<ProductImageMapping>(context);
var imageService = new ImageManagerService(imageRepo, imageMappingRepo);
var specificationRepo = new Repository<Specification>(context);
var specificationMappingRepo = new Repository<ProductSpecificationMapping>(context);
var specificationService = new SpecificationService(context, specificationRepo, specificationMappingRepo);
var productService = new ProductService(context, productRepo, categoryService, manufacturerService, imageService, specificationService);
Assert.Equal(1, productService.GetAllProduct().Count());
}
}
My productService has lots of dependencies to other services, repository and context.
Yes, you have a lot of dependent services and repositories. Since you already use Dependency Injection for your services, I suggest that you make use of an IoC Container. This will not only remove lots of code to setup your integration tests, it will also help you to resolve any service in your application easily.
You could create a class for your type mappings like this:
public class Services
{
private readonly DbContextOptions _options;
private readonly IUnityContainer _container;
public Services(DbContextOptions options)
{
_options = options;
_container = new UnityContainer();
RegisterTypes();
}
private void RegisterTypes()
{
_container.RegisterType<IApplicationDbContext, ApplicationDbContext>(new ContainerControlledLifetimeManager(), new InjectionConstructor(_options));
_container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
_container.RegisterType<ISpecificationService, SpecificationService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IImageManagerService, ImageManagerService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IRepository<ProductSpecificationMapping>, Repository<ProductSpecificationMapping>>(new ContainerControlledLifetimeManager());
// etc ...
}
public T Get<T>()
{
return _container.Resolve<T>();
}
}
Then you are able to minimize the code in your test which is needed to resolve a product service:
[Fact]
public void Add_writes_to_database()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: "Add_writes_to_database")
.Options;
var services = new Services(options);
var target = services.Get<IProductService>();
// to your testing
}
I haven't tested and verified these lines of code in VS, but it should give you an idea. We are using this approach with Unity in one of our application as well, and you can use your favorite IoC Container. You also need Interfaces for your Repositories and Services, but it is better to have them anyway :-)

Establishing session for Acumatica web services

Establishing session for Acumatica web services
I have a requirement where a session is to be established using web services, and then use that session to perform subsequent actions. E.g. Creating SOOrder and Shipment using web services using a previously created session/token.
SOOrder.Screen content = new SOOrder.Screen();
content.Url = InstanceUrl + “/Soap/SO301000.asmx";
content.CookieContainer = new System.Net.CookieContainer();
SOOrder.LoginResult lresult= content.Login(Username, password);
Using this, I have already obtained a session in lresult.Session.
Now, I would like to use this session in below shipmentcontent without calling login again.
SOShipment.Screen shipmentcontent = new SOShipment.Screen();
shipmentcontent.Url = InstanceUrl + "(W(3))/Soap/SO302000.asmx";
shipmentcontent.CookieContainer = new System.Net.CookieContainer();
shipmentcontent.Login(Username, password);
By package various screens in Web Services (SM.20.70.40) found under System -> Integration -> Configure -> Web Services you create a single end-point for all these screens. Consume this service end-point in you app, login only once and call out to all those screens.
thnx
If I understand you corectly you want to persist your login connection between different actions in Acumatia. In order to achieve this, I used the following approach:
Create graph:
public class Importer : PXGraph
{
}
Inside graph created following code:
public string GetHostUrl()
{
var nextIndex = HttpContext.Current.Request.Url.ToString().IndexOf("/", 7, StringComparison.Ordinal) + 1;
var urlStart = HttpContext.Current.Request.Url.ToString().IndexOf("/", nextIndex + 1, StringComparison.Ordinal);
var url = HttpContext.Current.Request.Url.ToString().Substring(0, urlStart);
return url;
}
public Screen Screen
{
get
{
var context = new Screen
{
CookieContainer = new CookieContainer(),
AllowAutoRedirect = true,
EnableDecompression = true,
Timeout = 1000000
};
var nextIndex = HttpContext.Current.Request.Url.ToString().IndexOf("/", 7, StringComparison.Ordinal) + 1;
var urlStart = HttpContext.Current.Request.Url.ToString().IndexOf("/", nextIndex + 1, StringComparison.Ordinal);
context.Url = HttpContext.Current.Request.Url.ToString().Substring(0, urlStart) + "/Soap/IMPORTET.asmx";
return context;
}
}
and then between different screens shared context of the Screen.
For example like this:
var scr = Screen;
var userName = PXAccess.GetUserName();
var password = GetUserPassword();
var context = Screen;
var lgRes = context.Login(userName, password);
but I preserved user password between different sessions

RhinoMocks - Unable to cast type foo to type bar when using non static Repository

I am trying out RhinoMocks (only just started, please be gentle!) and am confused as to why if I use this setup:
var mockRepos = new MockRepository();
var mockServiceProvider = mockRepos.DynamicMock<IServiceProvider>(null);
var mockContext = mockRepos.DynamicMock<IPluginExecutionContext>(null);
mockServiceProvider.Expect(x => x.GetService(typeof(IPluginExecutionContext))).Return(mockContext);
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
At some point in SomeClassOrOther, the method GetService is called
var context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));
and causes the exception:
Unable to cast object of type 'Castle.Proxies.ObjectProxyd0bf4b879a6341bbba3478cf1189d621' to type 'Microsoft.Xrm.Sdk.IPluginExecutionContext'.
However if I use:
var mockServiceProvider = MockRepository.GenerateMock<IServiceProvider>(null);
var mockContext = MockRepository.GenerateMock<IPluginExecutionContext>(null);
mockServiceProvider.Expect(x => x.GetService(typeof(IPluginExecutionContext))).Return(mockContext);
i.e. the static MockRepository.GenerateMock and it executes with no errors.
Where am I going wrong here?
I don't know why you are getting this very exception. However, when using the "old" non-static syntax, you get mocks in "Record" state. Before using them, you need to set them in Replay mode:
var mockRepos = new MockRepository();
var mockServiceProvider = mockRepos.DynamicMock<IServiceProvider>();
var mockContext = mockRepos.DynamicMock<IPluginExecutionContext>();
mockRepos.ReplayAll();
mockServiceProvider
.Stub(x => x.GetService(typeof(IPluginExecutionContext)))
.Return(mockContext);
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
You are mixing new AAA syntax and old Record/Replay syntax. When you are using Expect extension method and new AAA syntax, you don't need to operate on mocks repository and change its mode manually(Record/Replay). Create mocks with new static methods (which create mocks in replay mode) and verify expectations later:
// Arrange
var mockServiceProvider = MockRepository.GenerateMock<IServiceProvider>();
var mockContext = MockRepository.GenerateMock<IPluginExecutionContext>();
mockServiceProvider.Expect(x => x.GetService(typeof(IPluginExecutionContext)))
.Return(mockContext);
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
// Act
// Assert
mockServiceProvider.VerifyAllExpectations();
Here is old Record/Replay syntax for comparison:
var mockRepos = new MockRepository();
var mockServiceProvider = mockRepos.DynamicMock<IServiceProvider>();
var mockContext = mockRepos.DynamicMock<IPluginExecutionContext>();
Expect.Call(mockServiceProvider.GetService(typeof(IPluginExecutionContext)))
.Return(mockContext);
mockRepos.ReplayAll();
var someSampleClass = new SomeClassOrOther(mockServiceProvider);
// exercise your SUT
mockRepos.VerifyAll();