How to use the GlideApp generated api in the library module? - android-glide

Building library module. And in the sample application which is using the library module it has
#GlideModule
class DPAppGlideModule : AppGlideModule() {
override fun isManifestParsingEnabled(): Boolean {
return false
}
}
and in the library module has:
#GlideModule
public final class LibGlideModule extends LibraryGlideModule {
}
and in the library module it is using the GlideApp the generated api
fun ImageView.loadImg(imageUrl: String) {
var requestOptions : RequestOptions = RequestOptions()
requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL)
if (!TextUtils.isEmpty(imageUrl)) {
GlideApp.with(this.context)
.setDefaultRequestOptions(requestOptions)
.load(imageUrl)
.into(this)
}
}
But since this is the library module and cannot have decency on the application module, so it cannot compile
How to use the GlideApp generated api in the library module?
ref — https://bumptech.github.io/glide/doc/configuration.html

Just add
annotationProcessor com.github.bumptech.glide:compiler:4.8.0
dependency in your module gradle file. sync project then clean and rebuild it.
If your module using kotlin. change "annotationProcessor" to "kapt".
Be careful if you have others module dependency,make sure you use the right GlideApp Object. Maybe others module have it own GlideApp object

Related

.Net Maui Class library Dependancy injection for Platform specific code plugin

I am trying to create a plugin using .Net Maui class libraries that use native Android and iOS code. I tried using the Dependency Service using the Interface, but I get a null point when I try to Register the Interface.
Shared code
public class MyPlugin
{
public static DisplayModel()
{
IDeviceOrientationService service =
DependencyService.Get<IMyPlugin>();
var model = service.GetDeviceName();
}
}
public Interface IMyPlugin
{
string GetDeviceName();
}
Android platform
[assembly: Dependency(typeof(MyPlugin))]
public class MyPlugin:IMyPlugin
{
public string GetDeviceName
{
return "From Android";
}
}
This is just an example. Please help me understand if I am not going about this the correct way and any suggestion would be appreciated.

Xamarin Forms w/ Mobile Blazor Bindings - How to specify dependency injection in Blazor app for class defined in Android / iOS projects

Within my Blazor app, I am trying to determine the amount of available storage of the Android or iOS device.
I have found an answer here that is relevant:
Can I check available storage in the Device on Xamarin Forms?
As per the accepted answer, I have implemented the following:
Defined the Interface in the Blazor project
public interface IStorage
{
double GetRemainingStorage();
}
Created a class in the Android project
[assembly: Xamarin.Forms.Dependency(typeof(AndroidStorageManager))]
namespace MyApp.Android
{
public class AndroidStorageManager : IStorage
{
public double GetRemainingStorage()
{
var freeSpace = Android.OS.Environment.ExternalStorageDirectory.UsableSpace;
return freeSpace;
}
}
}
Created a class in the iOS project
[assembly: Xamarin.Forms.Dependency(typeof(iOSStorageManager))]
namespace MyApp.iOS
{
public class iOSStorageManager : IStorage
{
public double GetRemainingStorage()
{
var freeSpace = NSFileManager.DefaultManager.GetFileSystemAttributes(Environment.GetFolderPath(Environment.SpecialFolder.Personal)).FreeSize;
return freeSpace;
}
}
}
The Issue
Despite the definition of the dependencies with the [assembly: attribute, when my Blazor app tries to inject an instance of IStorage, it throws an exception:
Unable to resolve service for type 'IStorage' ...
Of course, I'm not able to define the dependency injection for IService in the Blazor app on startup, since the AndroidStorageManager and iOSStorageManager are defined in the device-specific projects which are already referencing the Blazor app.
I suspect I need some other way of defining the DI for IService in the Android and iOS apps, but can't see how to do it.
Can anyone offer any advice?
I seem to have found a workaround for my immediate issue, but I'm sure there must be a more elegant solution.
The exception was being generated when trying to inject an instance of the class associated with the IStorage interface.
public class MyManager {
private IStorage _storage;
public MyManager(IStorage storage) {
_storage = storage;
}
...
}
Rather then relying on the Blazor DI to resolve this dependency, I was able to use Xamarin.Forms DI to inject an instance manually, as follows:
public class MyManager {
private IStorage _storage;
public MyManager() {
_storage = DependencyService.Get<IStorage>();
}
...
}
I'm assuming that my original code wasn't working because Xamarin.Forms and Blazor are not sharing the same DI container. I'm not sure.
I'd be interested in anyone that can suggest a more elegant solution.

DI in Azure Functions

I have some class libraries that I use in my ASP.NET Web API app that handle all my backend stuff e.g. CRUD operations to multiple databases like Azure SQL Database, Cosmos DB, etc.
I don't want to re-invent the wheel and able to use them in a new Azure Functions that I'm creating in Visual Studio 2017. All my repository methods use an interface. So, how will I implement dependency injection in my new Azure function?
I'm not seeing any support for DI but I'm a bit confused. It appears Azure Functions are based on the same SDK as WebJobs and I think last year Microsoft had started supporting DI in WebJobs - I know for sure because I implemented it using Ninject.
Is there way around this so that I can use my existing libraries in my new Azure Functions project?
I see these two techniques in addition to the service locator (anti)pattern. I asked the Azure Functions team for their comments as well.
https://blog.wille-zone.de/post/azure-functions-dependency-injection/
https://blog.wille-zone.de/post/azure-functions-proper-dependency-injection/
There is an open feature request on the GitHub pages for Azure Functions concerning this matter.
However, the way I'm approaching this is using some kind of 'wrapper' entry point, resolve this using the service locator and and start the function from there.
This looks a bit like this (simplified)
var builder = new ContainerBuilder();
//register my types
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var functionLogic = scope.Resolve<IMyFunctionLogic>();
functionLogic.Execute();
}
This is a bit hacky of course, but it's the best there is until there is at the moment (to my knowledge).
I've seen the willie-zone blog mentioned a lot when it comes to this topic, but you don't need to go that route to use DI with Azure functions.
If you are using Version2 you can make your Azure functions non-static. Then you can add a public constructor for injecting your dependencies. The next step is to add an IWebJobsStartup class. In your startup class you will be able to register your services like you would for any other .Net Core project.
I have a public repo that is using this approach here: https://github.com/jedi91/MovieSearch/tree/master/MovieSearch
Here is a direct link to the startup class: https://github.com/jedi91/MovieSearch/blob/master/MovieSearch/Startup.cs
And here is the function: https://github.com/jedi91/MovieSearch/blob/master/MovieSearch/Functions/Search.cs
Hope this approach helps. If you are wanting to keep your Azure Functions static then the willie-zone approach should work, but I really like this approach and it doesn't require any third party libraries.
One thing to note is the Directory.Build.target file. This file will copy your extensions over in the host file so that DI will work once the function is deployed to Azure. Running the function locally does not require this file.
Azure Functions Depdendency Injection was announced at MSBuild 2019. Here's an example on how to do it:
[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient();
builder.Services.AddSingleton((s) => {
return new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTIONSTRING"));
});
builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
}
}
}
GitHub Example
Documentation
As stated above, it was just announced at Build 2019. It can now be setup almost exactly like you would in an ASP .Net Core app.
Microsoft Documentation
Short Blog I Wrote
Actually there is a much nicer and simpler way provided out of the box by Microsoft. It is a bit hard to find though. You simply create a start up class and add all required services here, and then you can use constructor injection like in regular web apps and web apis.
This is all you need to do.
First I create my start up class, I call mine Startup.cs to be consistent with Razor web apps, although this is for Azure Functions, but still it's the Microsoft way.
using System;
using com.paypal;
using dk.commentor.bl.command;
using dk.commentor.logger;
using dk.commentor.sl;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using org.openerp;
[assembly:Microsoft.Azure.WebJobs.Hosting.WebJobsStartup(typeof(dk.commentor.starterproject.api.Startup))]
namespace dk.commentor.starterproject.api
{
public class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
builder.Services.AddSingleton<ILogger, CommentorLogger>();
builder.Services.AddSingleton<IPaymentService, PayPalService>();
builder.Services.AddSingleton<IOrderService, OpenERPService>();
builder.Services.AddSingleton<ProcessOrderCommand>();
Console.WriteLine("Host started!");
}
}
}
Next I change the method call in the function from static to non-static, and I add a constructor to the class (which is now also non-static). In this constructor I simply add the services I require as constructor parameters.
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using dk.commentor.bl.command;
namespace dk.commentor.starterproject.api
{
public class ProcessOrder
{
private ProcessOrderCommand processOrderCommand;
public ProcessOrder(ProcessOrderCommand processOrderCommand) {
this.processOrderCommand = processOrderCommand;
}
[FunctionName("ProcessOrder")]
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger ProcessOrder called!");
log.LogInformation(System.Environment.StackTrace);
string jsonRequestData = await new StreamReader(req.Body).ReadToEndAsync();
dynamic requestData = JsonConvert.DeserializeObject(jsonRequestData);
if(requestData?.orderId != null)
return (ActionResult)new OkObjectResult($"Processing order with id {requestData.orderId}");
else
return new BadRequestObjectResult("Please pass an orderId in the request body");
}
}
}
Hopes this helps.
I would like to add my 2 cents to it. I used the technique that it's used by Host injecting ILogger. If you look at the Startup project I created GenericBindingProvider that implements IBindingProvider. Then for each type I want to be injected I register it as follow:
builder.Services.AddTransient<IWelcomeService, WelcomeService>();
builder.Services.AddSingleton<IBindingProvider, GenericBindingProvider<IWelcomeService>>();
The downside is that you need to register the type you want to be injected into the function twice.
Sample code:
Azure Functions V2 Dependency Injection sample
I have been using SimpleInjector perfectly fine in Azure Functions. Just create a class (let's call it IoCConfig) that has the registrations and make a static instance of that class in function class so that each instance will use the existing instance.
public interface IIoCConfig
{
T GetInstance<T>() where T : class;
}
public class IoCConfig : IIoCConfig
{
internal Container Container;
public IoCConfig(ExecutionContext executionContext, ILogger logger)
{
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(executionContext.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Container = new Container();
Configure(configurationRoot, logger);
}
public IoCConfig(IConfigurationRoot configurationRoot, ILogger logger)
{
Container = new Container();
Configure(configurationRoot, logger);
}
private void Configure(IConfigurationRoot configurationRoot, ILogger logger)
{
Container.RegisterInstance(typeof(IConfigurationRoot), configurationRoot);
Container.Register<ISomeType, SomeType>();
}
public T GetInstance<T>() where T : class
{
return Container.GetInstance<T>();
}
}
Then in root:
public static class SomeFunction
{
public static IIoCConfig IoCConfig;
[FunctionName("SomeFunction")]
public static async Task Run(
[ServiceBusTrigger("some-topic", "%SUBSCRIPTION_NAME%", Connection = "AZURE_SERVICEBUS_CONNECTIONSTRING")]
SomeEvent msg,
ILogger log,
ExecutionContext executionContext)
{
Ensure.That(msg).IsNotNull();
if (IoCConfig == null)
{
IoCConfig = new IoCConfig(executionContext, log);
}
var someType = IoCConfig.GetInstance<ISomeType>();
await someType.Handle(msg);
}
}
AzureFunctions.Autofac is very easy to use.
Just add a config file:
public class DIConfig
{
public DIConfig(string functionName)
{
DependencyInjection.Initialize(builder =>
{
builder.RegisterType<Sample>().As<ISample>();
...
}, functionName);
}
}
Add the DependencyInjectionConfig attribute then inject:
[DependencyInjectionConfig(typeof(DIConfig))]
public class MyFunction
{
[FunctionName("MyFunction")]
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequestMessage request,
TraceWriter log,
[Inject]ISample sample)
{
https://github.com/introtocomputerscience/azure-function-autofac-dependency-injection
I think this is a better solution:
https://github.com/junalmeida/autofac-azurefunctions
https://www.nuget.org/packages/Autofac.Extensions.DependencyInjection.AzureFunctions
Install the NuGet in your project and then make a Startup.cs and put this in it:
[assembly: FunctionsStartup(typeof(Startup))]
public class Startup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder
.UseAppSettings() // this is optional, this will bind IConfiguration in the container.
.UseAutofacServiceProviderFactory(ConfigureContainer);
}
private void ConfigureContainer(ContainerBuilder builder)
{
// do DI registration against Autofac like normal! (builder is just the normal ContainerBuilder from Autofac)
}
...
Then in your function code you can do normal constructor injection via DI:
public class Function1 : Disposable
{
public Function1(IService1 service1, ILogger logger)
{
// logger and service1 injected via autofac like normal
// ...
}
[FunctionName(nameof(Function1))]
public async Task Run([QueueTrigger("myqueue-items", Connection = "AzureWebJobsStorage")]string myQueueItem)
{
//...
Support for Dependency injection begins with Azure Functions 2.x which means Dependency Injection in Azure function can now leverage .NET Core Dependency Injection features.
Before you can use dependency injection, you must install the following NuGet packages:
Microsoft.Azure.Functions.Extensions
Microsoft.NET.Sdk.Functions
Having Dependency Injection eases things like DBContext, Http client usage (Httpclienfactory), Iloggerfactory, cache support etc.
Firstly, update the Startup class as shown below
namespace DemoApp
{
public class Startup: FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<IHelloWorld, HelloWorld>();
// Registering Serilog provider
var logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
builder.Services.AddLogging(lb => lb.AddSerilog(logger));
//Reading configuration section can be added here etc.
}
}
}
Secondly, Removal of Static keyword in Function class and method level
public class DemoFunction
{
private readonly IHelloWorld _helloWorld;
public DemoFunction(IHelloWorld helloWorld)
{
_helloWorld = helloWorld;
}
[FunctionName("HttpDemoFunction")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
}
If we look into above e.g. IHelloWorld is injected using .NET Core DI
**Note:**In-spite of having latest version of Azure function v3 for Dependency Injection to enable few steps are manual as shown above
Sample code on github can be found here

map hubs in referenced project

http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-signalr-20-self-host
In my case, my hubs are in a project referenced from the project code that spins up the self-hosted application.
On the line connection.Start().Wait(); I get an exception. The following is the sequence of exceptions thrown at that line:
The specified registry key does not exist System.IO.IOException
'MessageHub' Hub could not be resolved InvalidOperationException
The remote server returned an error: (500) Internal Server Error WebException
The signature of the message hub class in the referenced project is public class MessageHub : Hub.
Update: To test the theory, I moved the hub class from the referenced project into my test project and updated the namespace. It worked. So I think the theory here is sound... default hub resolution does not find hubs in referenced project or in separate namespace.
How can I convince MapHubs to find the test hub in the referenced project?
I think that I have found an answer to this.
After doing some digging around the source code it seems that SignalR uses the following method to designate an IAssemblyLocator to locate Hubs.
internal static RouteBase MapHubs(this RouteCollection routes, string name, string path, HubConfiguration configuration, Action<IAppBuilder> build)
{
var locator = new Lazy<IAssemblyLocator>(() => new BuildManagerAssemblyLocator());
configuration.Resolver.Register(typeof(IAssemblyLocator), () => locator.Value);
InitializeProtectedData(configuration);
return routes.MapOwinPath(name, path, map =>
{
build(map);
map.MapHubs(String.Empty, configuration);
});
}
public class BuildManagerAssemblyLocator : DefaultAssemblyLocator
{
public override IList<Assembly> GetAssemblies()
{
return BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList();
}
}
public class DefaultAssemblyLocator : IAssemblyLocator
{
public virtual IList<Assembly> GetAssemblies()
{
return AppDomain.CurrentDomain.GetAssemblies();
}
}
This got me to try to simply add my external assembly to current domain because although it was referenced it was not being loaded.
So before calling WebApp.Start I call the following line.
static void Main(string[] args)
{
string url = "http://localhost:8080";
// Add this line
AppDomain.CurrentDomain.Load(typeof(Core.Chat).Assembly.FullName);
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
Where Core.Chat is simply the Hub class I'm using.
And then the hubs defined in referenced assembly are loaded.
There might be a more straight forward way to go about this but I could not find anything in the documentation.
Hope this helps.

Flex + BlazeDS + Multi module maven project

I've got a multi module Maven project (about 10 modules) where 2 of the modules are a flex project and its corresponding server project, communicating via BlazeDS.
The server module is dependent on another module containing common things, shared over the whole project. When using objects from the common module, the objects aren't serialized and sent via AMF to the SWF. Everything in the server-module is serialized and is working fine, but the objects from the common module (which has valid values on the server side) is not sent to the client.
I'm using Flexmojos to build this. What do I have to do to make the classes in the common project available for serialization, and being able to use them as RemoteClass-objects in my swf-project?
The basic structure is similar to this (I've tried so simplify it quite a bit):
swf-module (Flex):
Class MyObject.as:
package swf.model {
[RemoteClass(alias="server.model.MyObject")]
public class MyObject {
public var name:String;
public var common:MyCommonObject;
}
}
Class MyCommonObject.as:
package swf.model {
[RemoteClass(alias="common.model.MyCommonObject")]
public class MyCommonObject {
public var commonNumber:Number; }
}
server-module (Java):
Class MyObject.java:
package server.model;
import common.model.MyCommonObject;
public class MyObject {
private String name;
private MyCommonObject common;
public MyObject() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MyCommonObject getCommon() {
return common;
}
public void setCommon(MyCommonObject common) {
this.common= common;
}
}
common-module (Java)
Class MyCommonObject.java:
package common.model;
public class MyCommonObject{
private Double commonNumber;
public MyCommonObject() {}
public Double getCommonNumber() {
return commonNumber;
}
public void setCommonNumber(Double commonNumber) {
this.commonNumber= commonNumber;
}
}
Java server side DTOs and ActionScript client DTOs are independent. I mean the following. When your BlazeDS services return AMF-serialized DTOs their binary structure is described by AMF format. And AMF transfer data contains full classpath which you describe on a client side using RemoteClass metadata. In this way client Flex project and Java server project haven't dependencies on each other in process of building. But you can build them together to produce the same WAR which contains both client and server part.
I have actually had to do this, you can go here, get the source for BlazeDS, add it to your project and debug to your heart's content.
I Think your common-module JAR is not in classpath of Flex module/WAR/BlazeDS,
try to put common module JAR in Flex modules war
means PUT {common module}.jar in {BlazeDS}\WEB-INF\lib\ on deployment
if its not there.
Hopes it works

Resources