Does anybody have a simple example of usage?
https://fatfreeframework.com/3.6/quick-reference#CONTAINER page
seem to me not really explanatory, but generally i need to figure a nice way to auto-inject $db_connection object just when/where needed, e.g.
In class's beforeRoute() method for smooth route resolving
When porting selfoss to use DI, I chose Dice as suggested in the docs you linked. I set up the container to use only a single shared instance of the DB class and pass it the connection string:
$f3 = Base::instance();
$dice = new Dice\Dice;
$host = $f3->get('db_host');
$database = $f3->get('db_database');
$dsn = "pgsql:host=$host; dbname=$database";
$dbParams = [
$dsn,
$f3->get('db_username'),
$f3->get('db_password')
];
$dice->addRule(DB\SQL::class, [
'constructParams' => $dbParams,
'shared' => true,
]);
$f3->set('CONTAINER', function($class) use ($dice) {
return $dice->create($class);
});
Then F3 will use the Dice container to create classes so controllers and any of their dependencies will be passed the instantiated dependencies in the constructor:
namespace daos;
class Items {
private DB\SQL $db;
public function __construct(DB\SQL $db) {
$this->db = $db;
}
public function fetchAll() {
$entries = $this->db->exec(…);
…
}
}
See the selfoss source code for a full example of how to configure the dependency container.
So, i've opted for singleton:
// Database class
class DB
{
private static $_instance = null;
private $dbconn = null;
// config files should better be located in more secure dir
const DB_HOST = '127.0.0.1';
const DB_NAME = 'my_db_name';
const DB_USER = 'my_db__user';
const DB_PASS = 'my_db_passw';
const CHARSET = 'utf8';
const DB_PREFIX = '';
///////////////////////////////////
private function __construct () {
$this->dbconn=new DB\SQL(
'mysql:host='.self::DB_HOST.';port='.self::DB_PORT.';dbname='.self::DB_NAME,
self::DB_USER,
self::DB_PASSW,
$options = array(
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_PERSISTENT => FALSE)
);
}
////////////////////////////////////
public static function getInstance() {
if (!self::$_instance) {
self::$_instance = new DB();
}
return self::$_instance;
}
//////////////////////////////////
public function connect() {
if ($this->dbconn) {
echo 'Hooray - 1st stage connected!';
return $this->dbconn;
}
else echo '<br>Sad enough, no connection :(((';
}
///////////// ///////////////// ////////////////////
private function __clone() { }
private function __wakeup() { }
}
Sorry for dummyness, i've just discovered for myself built in \Prefab class (to be extended for singletons), so the above DB connection i'd rather do LIKE%:
class DB extends \Prefab {
private $dbconn;
// ..then just do connection thing
public function connect() {
//////
}
}
Related
Consider this class that is used as a data model in a Model-View-Controller scenario (I'm using TypeScript 3.5):
export class ViewSource {
private viewName : string;
private viewStruct : IViewStruct;
private rows : any[];
private rowIndex : number|null;
constructor(viewName : string) {
// Same as this.setViewName(viewName);
this.viewName = viewName;
this.viewStruct = api.meta.get_view_struct(viewName);
if (!this.viewStruct) {
throw new Error("Clould not load structure for view, name=" + (viewName));
}
this.rows = [];
this.rowIndex = null;
}
public setViewName = (viewName: string) => {
this.viewName = viewName;
this.viewStruct = api.meta.get_view_struct(viewName);
if (!this.viewStruct) {
throw new Error("Clould not load structure for view, name=" + (viewName));
}
this.rows = [];
this.rowIndex = null;
}
public getViewStruct = ():IViewStruct => { return this.viewStruct; }
public getCellValue = (rowIndex: number, columnName: string) : any => {
const row = this.rows[rowIndex] as any;
return row[columnName];
}
}
This is not a complete class, I only included a few methods to demonstrate the problem. ViewSource is a mutable object. It can be referenced from multiple parts of the application. (Please note that being a mutable object is a fact. This question is not about choosing a different data model that uses immutable objects.)
Whenever I want to change the state of a ViewSource object, I call its setViewName method. It does work, but it is also very clumsy. Every line of code in the constructor is repeated in the setViewName method.
Of course, it is not possible to use this constructor:
constructor(viewName : string) {
this.setViewName(viewName);
}
because that results in TS2564 error:
Property 'viewStruct' has no initializer and is not definitely assigned in the constructor.ts(2564)
I do not want to ignore TS2564 errors in general. But I also do not want to repeat all attribute initializations. I have some other classes with even more properties (>10), and the corresponding code duplication looks ugly, and it is error prone. (I might forget that some things have to bee modified in two methods...)
So how can I avoid duplicating many lines of code?
I think the best method to avoid code duplication in this case would be to create a function that contains the initialization code, but instead of setting the value, it retunrs the value that need to be set.
Something like the following:
export class ViewSource {
private viewName : string;
private viewStruct : IViewStruct;
private rows : any[];
private rowIndex : number|null;
constructor(viewName : string) {
const {newViewName, newViewStruct, newRows, newRowIndex} = this.getNewValues(viewName);
this.viewName = newViewName;
this.newViewStruct = newViewStruct;
// Rest of initialization goes here
}
public setViewName = (viewName: string) => {
const {newViewName, newViewStruct, newRows, newRowIndex} = this.getNewValues(viewName);
// Rest of initialization goes here
}
privat getNewValues = (viewName) => {
const newViewName = viewName;
const newViewStruct = api.meta.get_view_struct(viewName);
if (!newViewStruct) {
throw new Error("Clould not load structure for view, name=" + (viewName));
}
const newRows = [];
const newRowIndex = null;
return {newViewName, newViewStruct, newRows, newRowIndex};
}
}
This way the only thing you duplicate is setting the values, not calculating them, and if the values calculations will get more complicated you can simply expand the returned value.
A less complex approach than the accepted answer is to use the //#ts-ignore[1] comment above each member that is initialized elsewhere.
Consider this contrived example
class Foo {
// #ts-ignore TS2564 - initialized in the init method
a: number;
// #ts-ignore TS2564 - initialized in the init method
b: string;
// #ts-ignore TS2564 - initialized in the init method
c: number;
constructor(a: number, b: string) {
if(a === 0) {
this.init(a,b,100);
} else {
this.init(a,b,4912);
}
}
private init(a: number, b: string, c: number): void {
this.a = a;
this.b = b;
this.c = c;
}
}
Since TypeScript 3.9 there exists the //#ts-expect-error[2] comment, but I think #ts-ignore is suitable.
[1] Suppress errors in .ts files
[2] TS expect errors comment
Since TypeScript 2.7 you can use the definite assignment assertion modifier which means adding an exclamation mark between the variable name and the colon:
private viewName!: string
This has the same effect as adding a // #ts-ignore TS2564 comment above it as #RamblinRose suggested.
I'm trying to create a decorator that requires dependency injection.
For example:
#Injectable()
class UserService{
#TimeoutAndCache(1000)
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}
The #TimeoutAndCache returns a new promise which does the following:
if call takes longer than 1000ms, returns a rejection and when the call completes, it stores to redis (so that it can be fetched next time).
If call takes less than 1000ms, simply returns the result
export const TimeoutAndCache = function timeoutCache(ts: number, namespace) {
return function log(
target: object,
propertyKey: string,
descriptor: TypedPropertyDescriptor<any>,
) {
const originalMethod = descriptor.value; // save a reference to the original method
descriptor.value = function(...args: any[]) {
// pre
let timedOut = false;
// run and store result
const result: Promise<object> = originalMethod.apply(this, args);
const task = new Promise((resolve, reject) => {
const timer = setTimeout(() => {
if (!timedOut) {
timedOut = true;
console.log('timed out before finishing');
reject('timedout');
}
}, ts);
result.then(res => {
if (timedOut) {
// store in cache
console.log('store in cache');
} else {
clearTimeout(timer);
// return the result
resolve(res);
}
});
});
return task;
};
return descriptor;
};
};
I need to inject a RedisService to save the evaluated result.
One way I could inject Redis Service in to the UserService, but seems kind ugly.
You should consider using an Interceptor instead of a custom decorator as they run earlier in the Nest pipeline and support dependency injection by default.
However, because you want to both pass values (for cache timeout) as well as resolve dependencies you'll have to use the mixin pattern.
import {
ExecutionContext,
Injectable,
mixin,
NestInterceptor,
} from '#nestjs/common';
import { Observable } from 'rxjs';
import { TestService } from './test/test.service';
#Injectable()
export abstract class CacheInterceptor implements NestInterceptor {
protected abstract readonly cacheDuration: number;
constructor(private readonly testService: TestService) {}
intercept(
context: ExecutionContext,
call$: Observable<any>,
): Observable<any> {
// Whatever your logic needs to be
return call$;
}
}
export const makeCacheInterceptor = (cacheDuration: number) =>
mixin(
// tslint:disable-next-line:max-classes-per-file
class extends CacheInterceptor {
protected readonly cacheDuration = cacheDuration;
},
);
You would then be able to apply the Interceptor to your handler in a similar fashion:
#Injectable()
class UserService{
#UseInterceptors(makeCacheInterceptor(1000))
async getUser(id:string):Promise<User>{
// Make a call to db to get all Users
}
}
How to use DecorateAllWith to decorate with a DynamicProxy all instances implements an interface?
For example:
public class ApplicationServiceInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// ...
invocation.Proceed();
// ...
}
}
public class ApplicationServiceConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.CanBeCastTo<IApplicationService>() && type.IsInterface)
{
var proxyGenerator = new ProxyGenerator();
// ??? how to use proxyGenerator??
// ???
registry.For(type).DecorateAllWith(???); // How to use DecorateAllWith DynamicProxy ...??
}
}
}
I could decorate some interfaces to concrete types using (for example):
var proxyGenerator = new ProxyGenerator();
registry.For<IApplicationService>().Use<BaseAppService>().DecorateWith(service => proxyGenerator.CreateInterfaceProxyWithTargetInterface(....))
But havent able to using DecorateAll to do this.
To call registry.For<>().Use<>().DecorateWith() I have to do this:
if (type.CanBeCastTo<IApplicationService>() && !type.IsAbstract)
{
var interfaceToProxy = type.GetInterface("I" + type.Name);
if (interfaceToProxy == null)
return null;
var proxyGenerator = new ProxyGenerator();
// Build expression to use registration by reflection
var expression = BuildExpressionTreeToCreateProxy(proxyGenerator, type, interfaceType, new MyInterceptor());
// Register using reflection
var f = CallGenericMethod(registry, "For", interfaceToProxy);
var u = CallGenericMethod(f, "Use", type);
CallMethod(u, "DecorateWith", expression);
}
Only for crazy minds ...
I start to get very tired of StructureMap, many changes and no documentation, I have been read the source code but ... too many efforts for my objective ...
If someone can give me a bit of light I will be grateful.
Thanks in advance.
In addition ... I post here the real code of my helper to generate the expression tree an register the plugin family:
public static class RegistrationHelper
{
public static void RegisterWithInterceptors(this Registry registry, Type interfaceToProxy, Type concreteType,
IInterceptor[] interceptors, ILifecycle lifecycle = null)
{
var proxyGenerator = new ProxyGenerator();
// Generate expression tree to call DecoreWith of StructureMap SmartInstance type
// registry.For<interfaceToProxy>().Use<concreteType>()
// .DecoreWith(ex => (IApplicationService)
// proxyGenerator.CreateInterfaceProxyWithTargetInterface(interfaceToProxy, ex, interceptors)
var expressionParameter = Expression.Parameter(interfaceToProxy, "ex");
var proxyGeneratorConstant = Expression.Constant(proxyGenerator);
var interfaceConstant = Expression.Constant(interfaceToProxy);
var interceptorConstant = Expression.Constant(interceptors);
var methodCallExpression = Expression.Call(proxyGeneratorConstant,
typeof (ProxyGenerator).GetMethods().First(
met => met.Name == "CreateInterfaceProxyWithTargetInterface"
&& !met.IsGenericMethod && met.GetParameters().Count() == 3),
interfaceConstant,
expressionParameter,
interceptorConstant);
var convert = Expression.Convert(methodCallExpression, interfaceToProxy);
var func = typeof(Func<,>).MakeGenericType(interfaceToProxy, interfaceToProxy);
var expr = Expression.Lambda(func, convert, expressionParameter);
// Register using reflection
registry.CallGenericMethod("For", interfaceToProxy, new[] {(object) lifecycle /*Lifecicle*/})
.CallGenericMethod("Use", concreteType)
.CallNoGenericMethod("DecorateWith", expr);
}
}
public static class CallMethodExtensions
{
/// <summary>
/// Call a method with Generic parameter by reflection (obj.methodName[genericType](parameters)
/// </summary>
/// <returns></returns>
public static object CallGenericMethod(this object obj, string methodName, Type genericType, params object[] parameters)
{
var metod = obj.GetType().GetMethods().First(m => m.Name == methodName && m.IsGenericMethod);
var genericMethod = metod.MakeGenericMethod(genericType);
return genericMethod.Invoke(obj, parameters);
}
/// <summary>
/// Call a method without Generic parameter by reflection (obj.methodName(parameters)
/// </summary>
/// <returns></returns>
public static object CallNoGenericMethod(this object obj, string methodName, params object[] parameters)
{
var method = obj.GetType().GetMethods().First(m => m.Name == methodName && !m.IsGenericMethod);
return method.Invoke(obj, parameters);
}
}
Almost two years later I have needed return this issue for a new project. This time I have solved it this time I have used StructureMap 4.
You can use a custom interceptor policy to decorate an instance in function of his type. You have to implement one interceptor, one interceptor policy and configure it on a registry.
The Interceptor
public class MyExInterceptor : Castle.DynamicProxy.IInterceptor
{
public void Intercept(Castle.DynamicProxy.IInvocation invocation)
{
Console.WriteLine("-- Call to " + invocation.Method);
invocation.Proceed();
}
}
The interceptor policy
public class CustomInterception : IInterceptorPolicy
{
public string Description
{
get { return "good interception policy"; }
}
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (pluginType == typeof(IAppService))
{
// DecoratorInterceptor is the simple case of wrapping one type with another
// concrete type that takes the first as a dependency
yield return new FuncInterceptor<IAppService>(i =>
(IAppService)
DynamicProxyHelper.CreateInterfaceProxyWithTargetInterface(typeof(IAppService), i));
}
}
}
Configuration
var container = new Container(_ =>
{
_.Policies.Interceptors(new CustomInterception());
_.For<IAppService>().Use<AppServiceImplementation>();
});
var service = container.GetInstance<IAppService>();
service.DoWork();
You can get a working example on this gist https://gist.github.com/tolemac/3e31b44b7fc7d0b49c6547018f332d68, in the gist you can find three types of decoration, the third is like this answer.
Using it you can configure the decorators of your services easily.
I've seen in polymer.dart they have:
class CustomTag {
final String tagName;
const CustomTag(this.tagName);
}
but how does that interact with the rest of the code? from just the code above I can't see how using #CustomTag('my-tag') actually does anything but creates a CustomTag which is then garbage collected since nothing is referencing it.
To answer the question in the title; these are called Annotations; they are simply const constructors.
To answer the second question; these are usually used for tooling (eg. #deprecated) or rewriting via a Transformer. You can access them at runtime using mirrors, but that's probably not practical/advisable for a production web app that gets converted to JavaScript.
Here's some sample code taken from this answer
import "dart:mirrors";
void main() {
var object = new Class1();
var classMirror = reflectClass(object.runtimeType);
// Retrieve 'HelloMetadata' for 'object'
HelloMetadata hello = getAnnotation(classMirror, HelloMetadata);
print("'HelloMetadata' for object: $hello");
// Retrieve 'Goodbye' for 'object.method'
var methodMirror = (reflect(object.method) as ClosureMirror).function;
Goodbye goodbye = getAnnotation(methodMirror, Goodbye);
print("'Goodbye' for object: $goodbye");
// Retrieve all 'Goodbye' for 'object.method'
List<Goodbye> goodbyes = getAnnotations(methodMirror, Goodbye);
print("'Goodbye's for object.method': $goodbyes");
// Retrieve all metadata for 'object.method'
List all = getAnnotations(methodMirror);
print("'Metadata for object.method': $all");
}
Object getAnnotation(DeclarationMirror declaration, Type annotation) {
for (var instance in declaration.metadata) {
if (instance.hasReflectee) {
var reflectee = instance.reflectee;
if (reflectee.runtimeType == annotation) {
return reflectee;
}
}
}
return null;
}
List getAnnotations(DeclarationMirror declaration, [Type annotation]) {
var result = [];
for (var instance in declaration.metadata) {
if (instance.hasReflectee) {
var reflectee = instance.reflectee;
if (annotation == null) {
result.add(reflectee);
} else if (reflectee.runtimeType == annotation) {
result.add(reflectee);
}
}
}
return result;
}
#HelloMetadata("Class1")
class Class1 {
#HelloMetadata("method")
#Goodbye("method")
#Goodbye("Class1")
void method() {
}
}
class HelloMetadata {
final String text;
const HelloMetadata(this.text);
String toString() => "Hello '$text'";
}
class Goodbye {
final String text;
const Goodbye(this.text);
String toString() => "Goodbye '$text'";
}
Output:
'HelloMetadata' for object: Hello 'Class1'
'Goodbye' for object: Goodbye 'method'
'Goodbye's for object.method': [Goodbye 'method', Goodbye 'Class1']
'Metadata for object.method': [Hello 'method', Goodbye 'method', Goodbye 'Class1']
I'm switching over from structure map to Autofac. I've use a caching pattern from Scott Millett's book ASP.net Design Patterns which implements an interface for both Cache and the Repository and switches in the appropriate object depending on the constructor parameter name
The interface looks like this
public interface ISchemeRepository
{
List<Scheme> GetSchemes();
}
The cache object looks like this
public class SchemeRepository : BaseRepository, ISchemeRepository
{
/***************************************************************
* Properties
***************************************************************/
private readonly ISchemeRepository schemeRepository;
/***************************************************************
* Constructors
***************************************************************/
public SchemeRepository()
: this(ObjectFactory.GetInstance<ISchemeRepository>(), ObjectFactory.GetInstance<IConfigurationSetting>())
{
}
public SchemeRepository(ISchemeRepository realSchemeRepository, IConfigurationSetting configurationSetting)
{
schemeRepository = realSchemeRepository;
this.configurationSetting = configurationSetting;
}
/**************************************************************
* Methods
***************************************************************/
public List<Scheme> GetSchemes()
{
string key = Prefix + "Schemes";
if (!MemoryCache.Default.Contains(key))
{
MemoryCache.Default.Add(key, schemeRepository.GetSchemes(), new CacheItemPolicy());
}
return (List<Scheme>)MemoryCache.Default.Get(key);
}
}
The repository looks like this
public class SchemeRepository : BaseLocalRepository, ISchemeRepository
{
/***************************************************************
* Properties
***************************************************************/
private readonly IConnectionSetting connectionSetting;
/***************************************************************
* Constructors
***************************************************************/
public SchemeRepository()
: this(ObjectFactory.GetInstance<IConnectionSetting>())
{
}
public SchemeRepository(IConnectionSetting connectionSetting)
{
this.connectionSetting = connectionSetting;
}
/**************************************************************
* Methods
***************************************************************/
public List<Scheme> GetSchemes()
{
var response = new List<Scheme>();
var conn = new SqlConnection(connectionSetting.CQBConnectionString);
var command = new SqlCommand("proc_GetSchemes", conn) { CommandType = CommandType.StoredProcedure };
conn.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
response.Add(
new Scheme
{
SchemeId = reader["Scheme_Id"].ToString().Trim(),
GuaranteeText = reader["Guarantee_Text"].ToString().Trim()
}
);
}
conn.Close();
return response;
}
}
The structure map call is below
InstanceOf<Repository.Local.Contract.IProviderRepository>().Is.OfConcreteType<Repository.Local.Core.ProviderRepository>().WithName("RealProviderRepository");
ForRequestedType<Repository.Local.Contract.IProviderRepository>().TheDefault.Is.OfConcreteType<Repository.Local.Cache.ProviderRepository>().CtorDependency<Repository.Local.Contract.IProviderRepository>().Is(x => x.TheInstanceNamed("RealProviderRepository"));
Structure map looks at the constructor and if it contains a parameter called "realSchemeRepository" then it implements the object that connect to the database, if not it implements the cache object that checks the cache and calls the database if nothing is in the cache and populates the cache.
How do I do this in Autofac? Is there a better way of doing this in Autofac?
I believe what you're asking how to do is set up a decorator between your two repository classes. I'm gonna pretend the two class names are CacheSchemeRepository and RealSchemeRepository because naming them exactly the same is confusing and terrible. Anyways...
builder.Register(c => new RealSchemeRepository(c.Resolve<IConnectionSetting>())
.Named<ISchemeRepository>("real");
builder.RegisterDecorator<ISchemeRepository>(
(c, inner) => new CacheSchemeRepository(inner, c.Resolve<IConfigurationSetting>()),
"real");