getInstance() Unresolved Kotlin - kotlin

Showing getInstance() unresolved reference when ever call.
class GlobalHolder {
private var pickerManager: PickerManager? = null
private val ourInstance = GlobalHolder()
fun getInstance() {
return ourInstance
}
private fun GlobalHolder(){}
fun getPickerManager(): PickerManager? {
return pickerManager
}
fun setPickerManager(pickerManager: PickerManager) {
this.pickerManager = pickerManager
}
}
Call
lateinit var pickerManager: PickerManager
pickerManager=GlobalHolder.getInstance().getPickerManager()
FYI
This is original Java class
public class GlobalHolder {
private PickerManager pickerManager;
private static GlobalHolder ourInstance = new GlobalHolder();
public static GlobalHolder getInstance() {
return ourInstance;
}
private GlobalHolder() {
}
public PickerManager getPickerManager() {
return pickerManager;
}
public void setPickerManager(PickerManager pickerManager) {
this.pickerManager = pickerManager;
}
}

You're willing to have a singleton, right? Make GlobalHolder an object, which will automatically provide a singleton:
object GlobalHolder {
private var pickerManager: PickerManager? = null
fun getPickerManager(): PickerManager? {
return pickerManager
}
fun setPickerManager(pickerManager: PickerManager) {
this.pickerManager = pickerManager
}
}
And then your instance like this:
GlobalHolder.getPickerManager()

Related

how to make reference type for string enum in kotlin and jacoco coverage testable

Converted a java class into kotlin in Android app, the jacoco coverage starts to show 0 coverage on a compiler generated function, which is not access able. Other ones seem fine in the report.
How to make reference type for string enum in kotlin and jacoco coverage testable
java code:
public final class Message {
private Message() { }
public static class MessageAction {
public static final String OPEN = "open";
public static final String VIEW_ALL = "view_all";
#Retention(RetentionPolicy.SOURCE)
#StringDef({OPEN, VIEW_ALL})
public #interface Action { }
public String mAction;
public MessageAction(#Action String action) {
this.mAction = action;
}
public String getMessageAction() {
return this.mAction;
}
}
}
in kotlin;
import androidx.annotation.StringDef
class Message private constructor() {
class MessageAction(#param:Action var messageAction: String) {
#kotlin.annotation.Retention(AnnotationRetention.SOURCE)
#StringDef(OPEN, VIEW_ALL)
annotation class Action
companion object {
const val OPEN = "open"
const val VIEW_ALL = "view_all"
}
}
}
this is sample of how it is used in java code:
public static void doSomeThing(#Nullable String message, #Message.MessageAction.Action String action) {
...
}
and the test:
#Test
public void test_messageAction() {
String testAction = "open";
Message.MessageAction action = new Message.MessageAction(Message.MessageAction.OPEN);
assertEquals(testAction, action.getMessageAction());
}
the jacoco test coverage result shows 0 covergate on the function setMessageAction(#NotNull String var1) which is in the decompiled java code.
And it is not visible from the code's autocomplete hint.
the kotlin decompiled java code:
public final class Message {
private Message() {
}
#Metadata( ...... )
public static final class MessageAction {
#NotNull
private String messageAction;
#NotNull
public static final String OPEN = "open";
#NotNull
public static final String VIEW_ALL = "view_all";
public static final Message.MessageAction.Companion Companion = new Message.MessageAction.Companion((DefaultConstructorMarker) null);
#NotNull
public final String getMessageAction() {
return this.messageAction;
}
public final void setMessageAction(#NotNull String var1) { //<=== coverage result shows it is not called
Intrinsics.checkNotNullParameter(var1, "<set-?>");
this.messageAction = var1;
}
public MessageAction(#NotNull String messageAction) {
Intrinsics.checkNotNullParameter(messageAction, "messageAction");
super();
this.messageAction = messageAction;
}
#Retention(AnnotationRetention.SOURCE)
#java.lang.annotation.Retention(RetentionPolicy.SOURCE)
#Metadata( ...... )
public #interface Action {
}
#Metadata( ...... )
public static final class Companion {
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
}
}
adding #JvmField resolves it
class MessageAction(#param:Action messageAction: String) {
#kotlin.annotation.Retention(AnnotationRetention.SOURCE)
#StringDef(OPEN, VIEW_ALL, CLEAR, TOUCH3D, PLAY, PAUSE, DISMISSED)
annotation class Action
#JvmField
var messageAction: String = messageAction
companion object {
const val OPEN = "open"
const val VIEW_ALL = "view_all"
}
}

How to assert/validate the JSON body and properties returned by a Micronaut controller

I am a Micronaut/Java beginner and I am trying to design some tests for my controllers. I could not find many examples online so here is my question.
Below is the controller with 2 #GET requests:
#Controller("/api/v1")
public class MyController {
private final ClientNetworkList clientNetworkList;
private final ClientStatus clientStatus;
public MyController(
ClientNetworkList clientNetworkList,
ClientStatus clientStatus
){
this.ClientNetworkList = clientNetworkList;
this.ClientStatus = clientStatus;
}
#Get(uri = "/networkList", produces = MediaType.APPLICATION_JSON_STREAM)
Flowable<NetworkListPackage> packagesNetworkList() {
return ClientNetworkList.fetchPackages();
}
#Get(uri = "/channels/{stringParm}/status/", produces = MediaType.APPLICATION_JSON_STREAM)
Flowable<ChannelStatusPackage> packagesStatus(stringParm) {
return ClientStatus.fetchPackages(genesis);
}
}
The java object POJOs:
#Introspected
public class NetworkListPackage {
private List<NetworkList> networkList = null;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public List<NetworkList> getNetworkList() {
return networkList;
}
public void setNetworkList(List<NetworkList> networkList) {
this.networkList = networkList;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
public class NetworkList {
private String name;
private Boolean authEnabled;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getAuthEnabled() {
return authEnabled;
}
public void setAuthEnabled(Boolean authEnabled) {
this.authEnabled = authEnabled;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
#Introspected
public class ChannelStatusPackage {
private String chaincodeCount;
private String txCount;
private String latestBlock;
private String peerCount;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public String getChaincodeCount() {
return chaincodeCount;
}
public void setChaincodeCount(String chaincodeCount) {
this.chaincodeCount = chaincodeCount;
}
public String getTxCount() {
return txCount;
}
public void setTxCount(String txCount) {
this.txCount = txCount;
}
public String getLatestBlock() {
return latestBlock;
}
public void setLatestBlock(String latestBlock) {
this.latestBlock = latestBlock;
}
public String getPeerCount() {
return peerCount;
}
public void setPeerCount(String peerCount) {
this.peerCount = peerCount;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
And the potential tests:
#MicronautTest
class MyControllerTest {
#Inject
#Client("/")
RxStreamingHttpClient client;
#Test
public void verifyChannelStatusPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
//when:
HttpRequest request = HttpRequest.GET("/api/v1/channels/{stringParam}/status/");
Flowable<ChannelStatusPackage> channelStatusPackageStream = client.jsonStream(request, ChannelStatusPackage.class);
Iterable<ChannelStatusPackage> channelStatusPackages = channelStatusPackageStream.blockingIterable();
//then:
//How to assert the returned body compared to the POJO?
//How to handle the parameter in the request url?
#Test
public void verifyNetworkListPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
//when:
HttpRequest request = HttpRequest.GET("/api/v1/networkList");
Flowable<NetworkListPackage> networkListPackageStream = client.jsonStream(request, NetworkListPackage.class);
Iterable<NetworkListPackage> networkListPackages = networkListPackageStream.blockingIterable();
//then:
//How to assert the returned body and compared to the POJO?
//How to assert the returned properties ?
}
}
Based on the previous code, how can I test that the returned bodies and properties of the requests matches the POJOs?
What are the usual test to be carried out?
Thank you very much for helping.
Normaly, the basic assertion start by testing the object type, so this should validate your schema.
An other way to test it is to use RestAssured, witch is a bit more readable.
You need to import the fallowing dependencies in you build.gradle
testImplementation("io.rest-assured:rest-assured:4.2.+")
testImplementation("io.rest-assured:json-schema-validator:4.2.+")
You need test annotation processor to enable micronaut injection and junit 5 for the BeforeEach.
The full test dependencies:
testAnnotationProcessor("io.micronaut:micronaut-inject-java")
testImplementation("org.junit.jupiter:junit-jupiter-api")
testImplementation("io.micronaut.test:micronaut-test-junit5")
testImplementation("io.rest-assured:rest-assured:4.2.+")
testImplementation("io.rest-assured:json-schema-validator:4.2.+")
testRuntime("org.junit.jupiter:junit-jupiter-engine")
Then you can wright your tests like that:
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
import io.micronaut.http.HttpStatus;
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.test.annotation.MicronautTest;
import io.restassured.RestAssured;
import javax.inject.Inject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
#MicronautTest
class MyControllerTest {
#Inject
private EmbeddedServer embeddedServer;
#BeforeEach
public void setUp() {
RestAssured.port = embeddedServer.getPort();
}
#Test
public void verifyChannelStatusPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
given()
.when()
.pathParam("stringParam", "value")
.get("/api/v1/channels/{stringParam}/status/")
.then()
.statusCode(HttpStatus.OK.getCode())
.body(
"chaincodeCount", equalTo("chaincodeCountValue"),
"txCount", equalTo("txCountValue"),
"latestBlock", equalTo("latestBlockValue"),
"peerCount", equalTo("peerCountValue"),
"additionalProperties.key1", equalTo("additionalPropertyValue1"),
"additionalProperties.key2", equalTo("additionalPropertyValue2")
);
}
#Test
public void verifyNetworkListPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
given()
.when()
.get("/api/v1/networkList")
.then()
.statusCode(HttpStatus.OK.getCode())
.body(
"networkList.name[0]", equalTo("nameValue0"),
"networkList.authEnabled[0]", equalTo("authEnabledValue0"),
"networkList.additionalProperties[0].key1", equalTo("additionalPropertiesValue1"),
"networkList.additionalProperties[0].key2", equalTo("additionalPropertyValue2")
);
}
}
This is not really the way you wanted to do your tests, but I hope it will help.
So I ended up using the "hasItems" matcher or/and the jackson schema matcher.
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
import io.micronaut.http.HttpStatus;
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.test.annotation.MicronautTest;
import io.restassured.RestAssured;
import javax.inject.Inject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.hamcrest.Matchers.hasItems;
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
#MicronautTest
class MyControllerTest {
#Inject
private EmbeddedServer embeddedServer;
#BeforeEach
public void setUp() {
RestAssured.port = embeddedServer.getPort();
}
#Test
public void verifyChannelStatusPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
given()
.when()
.pathParam("stringParam", "value")
.get("/api/v1/channels/{stringParam}/status/")
.then()
.statusCode(HttpStatus.OK.getCode())
.body(matchesJsonSchemaInClasspath("channelsStatus.json"))
.body("keySet()",hasItems(
"chaincodeCount",
"txCount",
"latestBlock",
"peerCount",
);
}
#Test
public void verifyNetworkListPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
given()
.when()
.get("/api/v1/networkList")
.then()
.statusCode(HttpStatus.OK.getCode())
.body(matchesJsonSchemaInClasspath("networkList.json"))
.body("networkList.keySet()",hasItems(
"name",
"authEnabled",
);
}
}
``
Another option is to use jsonPath similar to Spring Boot MockMvc ResultMatcher:
testImplementation 'com.jayway.jsonpath:json-path:2.4.0'
testImplementation 'org.hamcrest:hamcrest:2.2'
Get the response as HttpResponse<String> and then use JsonPath.parse(response.body()) to assert the json path:
#Test
public void verifyChannelStatusPackagesCanBeFetchedWithCompileTimeAutoGeneratedAtClient() {
URI uri = UriBuilder.of("/api/v1/channels/{stringParam}/status/").expand(singletonMap("stringParam", "value"));
HttpResponse<String> response = client.toBlocking().exchange(HttpRequest.GET(uri), String.class);
assertEquals(HttpStatus.OK, response.getStatus());
ReadContext ctx = JsonPath.parse(response.body());
assertThat(ctx.read("$"), isA(Object.class));
assertThat(ctx.read("$.chaincodeCount"), is("chaincodeCountValue"));
}
Example for an endpoint test using Micronaut vs Spring Boot

How to avoid cumbersome holder in kotlin

I have to deal with the following java code
abstract class ScriptResult {
void ifSuccess(Consumer<Object> block) {
}
void ifError(Consumer<Throwable> block) {
}
static class Success extends ScriptResult {
private final Object returnValue;
Success(Object returnValue) {
this.returnValue = returnValue;
}
#Override
void ifSuccess(Consumer<Object> block) {
block.accept(returnValue);
}
}
static class Error extends ScriptResult {
private final Throwable throwable;
Error(Throwable throwable) {
this.throwable = throwable;
}
#Override
void ifError(Consumer<Throwable> block) {
block.accept(throwable);
}
}
}
My kotlin tests make use of the following assertion helper:
private lateinit var scriptResult: ScriptResult
inline fun <reified T : Throwable> shouldHaveThrown(): T {
scriptResult.ifSuccess { result ->
fail("should have thrown ${T::class.java.name}, but returned `$result´")
}
lateinit var holder: T // (1)
scriptResult.ifError { throwable ->
if (throwable is T) {
holder = throwable // (2)
} else {
fail("expected ${T::class.java.name} to be thrown, but threw `$throwable´")
}
}
return holder // (3)
}
The assertion helper is effective. I can use it like so:
val thrown = execution.shouldHaveThrown<MissingMethodException>()
assertThat(thrown.message).contains("missedMethod")
But I suspect there is a more idiomatic way to return throwable from shouldHaveThrown, then to (1) declaring a holder, (2) assigning it and (3) eventually returning it. How?

closed generic type registration - Autofac – cannot resolve parameter x of constructor

I am getting the following exception:
"None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository' can be invoked with the available services and parameters:\r\nCannot resolve parameter 'NetCore.DAL.EF.DatabaseFactory1[NetCore.DAL.EF.AppDbContext] databaseFactory' of constructor 'Void .ctor(NetCore.DAL.EF.DatabaseFactory1[NetCore.DAL.EF.AppDbContext])'."
Here is the Autofac registration info for SystemSettingRepository:
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28] = {Activator = SystemSettingRepository (ReflectionActivator), Services = [Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository, Dcs.NetCore.Infrastructure.Common.IRepository`1[[Dcs.NetCore.ApplicationCore.BLL.Domain.Entities.Common.SystemSetting, Dcs.NetCore.ApplicationCore.BLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].Target.Services[0].ServiceType = {Dcs.NetCore.ApplicationCore.BLL.Domain.Features.Common.SystemSettings.ISystemSettingRepository}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].Target.Services[1].ServiceType = {Dcs.NetCore.Infrastructure.Common.IRepository`1[Dcs.NetCore.ApplicationCore.BLL.Domain.Entities.Common.SystemSetting]}
autofacServiceProvider.Non-Public members._lifetimeScope.ComponentRegistry.Registrations[28].Target.Services[2].ServiceType = {NetCore.DAL.EF.Repositories.Core.Common.SystemSettingRepository}
As you can see, the services are registered. However, the databaseFactory parameter is not. Here is my code:
public class Startup
{
…
public IServiceProvider ConfigureServices(IServiceCollection services)
{
…
return AutofacBuilder();
}
private AutofacServiceProvider AutofacBuilder()
{
var builder = new ContainerBuilder();
builder.RegisterModule<AutofacModule_AspNetCore>();
builder.Populate(_services);
this.AutofacContainer = builder.Build();
var autofacServiceProvider = new AutofacServiceProvider(this.AutofacContainer);
return autofacServiceProvider;
}
}
public class AutofacModule_AspNetCore : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
RegisterDbContexts();
RegisterComponents();
}
private void RegisterComponents()
{
_builder.RegisterGeneric(typeof(DatabaseFactory<>))
.As(typeof(IDatabaseFactory<>))
.InstancePerDependency();
_builder.RegisterAssemblyTypes(_assembly)
.AsClosedTypesOf(typeof(IRepository<>))
.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
(p, i) => i.Resolve<DatabaseFactory<AppDbContext>>()))
//.WithParameter("databaseFactory", new DatabaseFactory<AppDbContext>())
//.WithParameter(ResolvedParameter//.ForNamed<IDbContext>("coreDomainDbContext"));
//.WithParameter("databaseFactory", )
.InstancePerDependency();
}
private void RegisterDbContexts()
{
RegisterAppDbContextInstance();
}
private void RegisterAppDbContextInstance()
{
// register DbContextOptionsBuilderHelper
_builder.RegisterType<AppDbContextOptionsBuilderHelper>()
.InstancePerDependency();
// configure DbContextOptions
var dbContextOptionsBuilderHelper = new AppDbContextOptionsBuilderHelper();
var dbContextOptionsBuilder = dbContextOptionsBuilderHelper.GetDbContextOptionsBuilder();
// register DbContext
_builder.RegisterType<AppDbContext>()
.WithParameter("options", dbContextOptionsBuilder.Options)
.InstancePerDependency();
}
}
public class DatabaseFactory<T> : Disposable, IDatabaseFactory<T>
where T : DbContext //, new()
{
private T _dbContext;
private AppDbContextOptionsBuilderHelper _appDbContextOptionsBuilderHelper;
private DefaultDbContextOptionsBuilderHelper _defaultDbContextOptionsBuilderHelper;
public DatabaseFactory()
{
this._appDbContextOptionsBuilderHelper = new AppDbContextOptionsBuilderHelper(); // TODO: refactor to ctor injection
this._defaultDbContextOptionsBuilderHelper = new DefaultDbContextOptionsBuilderHelper(); // TODO: refactor to ctor injection
}
public T Get()
{
if (_dbContext == null)
Create();
return _dbContext;
}
private void Create()
{
switch (typeof(T).Name)
{
case "AppDbContext":
{
CreateAppDbContext();
break;
}
case "DefaultDbContext":
{
CreateDefaultDbContext();
break;
}
}
}
private void CreateAppDbContext()
{
var dbContextOptionsBuilder = _appDbContextOptionsBuilderHelper.GetDbContextOptionsBuilder();
this._dbContext = new AppDbContext(dbContextOptionsBuilder.Options) as T;
}
//protected override void DisposeCore()
//{
//
// cref: Autofac.Util.Disposable
//
// //TODO: should I override Autofac.Util.Disposable here?
// var msg = "DatabaseFactory.DisposeCore() executing";
// if (_dbContext != null)
// _dbContext.Dispose();
//}
}
public partial class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{ }
public AppDbContext()
{}
}
public class SystemSettingRepository : RepositoryBase<SystemSetting, AppDbContext>, ISystemSettingRepository
{
public SystemSettingRepository(DatabaseFactory<AppDbContext> databaseFactory)
: base(databaseFactory)
{ }
}
public interface ISystemSettingRepository : IRepository<SystemSetting>
{}
public partial interface IRepository<T> where T : class
{}
public abstract class RepositoryBase<T, U> : IRepositoryBase<T, U>
where T : class
where U : DbContext //, new()
{
private U _dbContext;
private readonly DbSet<T> _dbset;
protected RepositoryBase(DatabaseFactory<U> databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = DataContext.Set<T>();
}
protected virtual DatabaseFactory<U> DatabaseFactory
{
get;
private set;
}
protected virtual U DataContext
{
get { return _dbContext = DatabaseFactory.Get(); }
}
public virtual async Task<T> AddAsync(T dao)
{
EntityEntry<T> entityEntry = _dbset.Add(dao);
var result = await SaveChangesAsync();
if (result > 0 && entityEntry != null && entityEntry.Entity != null)
return entityEntry.Entity;
else
return null;
}
}
public interface IRepositoryBase<T, U>
where T : class
where U : DbContext //, new()
{ }
The issue is caused by the way of registration of DatabaseFactory<>. This type is registered as an interface IDatabaseFactory<>. But it is resolved as itself in lambda argument of method WithParameter() on registration of repositories:
_builder.RegisterAssemblyTypes(_assembly)
.AsClosedTypesOf(typeof(IRepository<>))
.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
// resolving type it self
// while it was registered as interface
(p, i) => i.Resolve<DatabaseFactory<AppDbContext>>()))
Autofac doesn't know how to resolve it, because it doesn't have corresponding registration. To make your code work you can resolve DatabaseFactory as an inteface like this:
.WithParameter(new ResolvedParameter((p, i) => p.Name == "databaseFactory",
(p, i) => i.Resolve<IDatabaseFactory<AppDbContext>>()))
Or add AsSelf() call to registration:
_builder.RegisterGeneric(typeof(DatabaseFactory<>))
.As(typeof(IDatabaseFactory<>))
// Register also as DatabaseFactory<>
.AsSelf()
.InstancePerDependency();

Ninject issue with contextual binding and Lazy<T>

Ninject doesn't seem to correctly use WhenInjectedInto contstraint while also using Lazy<T>. Check the following example. The OnLandAttack and the OnLandAttackLazy should each be using the Samurai instance. But the Lazy<T> version ends up with the SpecialNinja instance. I'm guessing it's because it's not actually initialized in the contructor? But the type should still be correctly registered I would think. Am I missing something? FYI, this is using Ninject 3.2.2 and the Ninject.Extensions.Factory extension 3.2.1
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Load(new WarriorModule());
var amphibious = kernel.Get<IAttack>("amphibious");
amphibious.Execute();
var onLand = kernel.Get<IAttack>("onLand");
onLand.Execute();
var onLandLazy = kernel.Get<IAttack>("onLandLazy");
onLandLazy.Execute();
Console.ReadKey();
}
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
Bind<IWarrior>().To<Samurai>().WhenInjectedInto<OnLandAttack>();
Bind<IWarrior>().To<Samurai>().WhenInjectedInto<OnLandAttackLazy>();
Bind<IWarrior>().To<SpecialNinja>(); // <-- for everything else
Bind<IAttack>().To<AmphibiousAttack>().Named("amphibious");
Bind<IAttack>().To<OnLandAttack>().Named("onLand");
Bind<IAttack>().To<OnLandAttackLazy>().Named("onLandLazy");
}
}
public interface IWarrior
{
void Attack();
}
public class Samurai : IWarrior
{
public void Attack()
{
Console.WriteLine("\tSamurai Attack");
}
}
public class SpecialNinja : IWarrior
{
public void Attack()
{
Console.WriteLine("\tSpecial Ninja Attack");
}
}
public interface IAttack
{
void Execute();
}
public class OnLandAttack : IAttack
{
private readonly IWarrior warrior;
public OnLandAttack(IWarrior warrior)
{
this.warrior = warrior;
}
public void Execute()
{
Console.WriteLine("Begin OnLand attack");
this.warrior.Attack();
}
}
public class OnLandAttackLazy : IAttack
{
private readonly Lazy<IWarrior> warrior;
public OnLandAttackLazy(Lazy<IWarrior> warrior)
{
this.warrior = warrior;
}
public void Execute()
{
Console.WriteLine("Begin OnLandLazy attack");
this.warrior.Value.Attack();
}
}
public class AmphibiousAttack : IAttack
{
private readonly IWarrior warrior;
public AmphibiousAttack(IWarrior warrior)
{
this.warrior = warrior;
}
public void Execute()
{
Console.WriteLine("Begin Amphibious attack");
this.warrior.Attack();
}
}