Upgrading Unity to 5.11 - unity-container

We have an old code which has
public override void PreBuildUp(IBuilderContext context)
{
var type = context.OriginalBuildKey.Type;
Now it has to be
public override void PreBuildUp(ref BuilderContext context)
{
What's corresponding to OriginalBuildKey property in the context that is now of type BuilderContext? I can't figure it out.

I recently had the same issue trying to update AutoMoq-Unity5 to Unity 5.11.
Comparing the current version of BuilderContext.cs with the earlier 5.9 version I saw the change was
From
[DebuggerDisplay("Resolving: {OriginalBuildKey.Type}, Name: {OriginalBuildKey.Name}")]
public class BuilderContext : IBuilderContext
To
[DebuggerDisplay("Resolving: {Type}, Name: {Name}")]
public struct BuilderContext : IResolveContext
So as you mentioned I changed my code from
public override void PreBuildUp(IBuilderContext context)
{
To use the BuilderContext by reference
public override void PreBuildUp(ref BuilderContext context)
{
And where I used OriginalBuildKey.Type I now have changed from
private static Type GetTheTypeFromTheBuilderContext(IBuilderContext context)
{
return (context.OriginalBuildKey).Type;
}
to
private static Type GetTheTypeFromTheBuilderContext(IResolveContext context)
{
return context.Type;
}
My unit tests are passing at that.

Related

Can't find method Shiny.IShinyStartup.ConfigureServices with Prism 8

The error I'm getting during app startup is the following:
Parent class vtable failed to initialize, due to: Could not load list of method overrides due to Method not found: void Shiny.IShinyStartup.ConfigureServices(Microsoft.Extensions.DependencyInjection.IServiceCollection) assembly:/Users/merickson/Library/Developer/CoreSimulator/Devices/D19E269D-A3E5-46C2-BB9C-94A122EA02DC/data/Containers/Bundle/Application/F9A34529-8F64-4868-8D7F-389C77DB54BC/PrismSizeTest.iOS.app/Shiny.Prism.dll type:PrismStartup member:(null)
I'm not sure if I'm missing a NuGet, maybe wrong version of one or more NuGets, or am I initializing something wrong? Any help is appreciated.
I've been able to replicate this with a bare bones solution which I can provide if necessary. Here are the main files involved:
App.xaml.cs
public partial class App : PrismApplicationBase
{
public App(IPlatformInitializer initializer)
: base(initializer)
{
}
protected override async void OnInitialized()
{
InitializeComponent();
await NavigationService.NavigateAsync("NavigationPage/MainPage");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
}
protected override IContainerExtension CreateContainerExtension() => ContainerLocator.Current;
}
AppDelegate.cs
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
ShinyHost.Init(new ApplePlatform(), new MyStartup());
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App(new iOSInitializer()));
return base.FinishedLaunching(app, options);
}
}
public class iOSInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
// Register any platform specific implementations
}
}
MyStartup.cs
public class MyStartup : PrismStartup
{
protected override void ConfigureServices(IServiceCollection services)
{
services.UseGps<GpsDelegate>();
}
}
NuGets installed:
There is nothing directly wrong with the code... however the latest versions of Shiny have breaking ABI changes that make Shiny.Prism and Shiny.Core incompatible which is the result of the issue shown here...
For more information you can track the issue at: https://github.com/dansiegel/Prism.Container.Extensions/issues/183

ActionFilterAttribute - retrieve querystring .net core 2.2

I'm developing a FilterAttribute and would like to read from the query string.
I receive the error as shown below. According to some blog entries this is an acceptable practice https://jacstech.wordpress.com/2013/07/23/retrieving-parameters-from-the-query-string-in-the-url-in-net/ but am thinking this has change in .net core 2.2
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.Controller is Controller controller)
{
...
controller.ViewBag.lnsalesquotationnumber = filterContext.HttpContext.Request.QueryString["lnsalesquotationnumber"];
}
}
ERPFilter.cs(32,61): error CS0021: Cannot apply indexing with [] to an expression of type 'QueryString' [C:\Projects\FarrisCosting\Projects.csproj]
I have get QueryString value this using code
public class TestFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
var queryStringValue= context.HttpContext.Request.Query["QueryStringKey"].ToString();
}
}

Make TvInputService display an overlay

I'm trying to write a most simple TvInputService, that will display an overlay using TIF Companion Library.
The Live Channels application already recognizes my channel Simple Channel declared in my EpgSyncJobService subclass.
My Program is displayed in the Live Channels application's EPG as currently presented one.
However, all I can see is the blue spinner, as if the channel didn't "tune".
What am I doing wrong?
public class MyTvInputService extends BaseTvInputService {
#Override
public final BaseTvInputService.Session onCreateSession(String inputId) {
BaseTvInputService.Session session = new MyTvInputSession(this, inputId);
session.setOverlayViewEnabled(true);
return super.sessionCreated(session);
}
class MyTvInputSession extends BaseTvInputService.Session {
public MyTvInputSession(Context context, String inputId) {
super(context, inputId);
}
#Override
public View onCreateOverlayView() {
mTextView = new TextView(MyTvInputService.this);
mTextView.setText("This is an example overlay");
mTextView.setTextColor(Color.RED);
mTextView.setVisibility(View.VISIBLE);
mTextView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
return mTextView;
}
#Override
public boolean onPlayProgram(Program program, long startPosMs) {
return true;
}
#Override
public boolean onPlayRecordedProgram(RecordedProgram recordedProgram) {
return true;
}
#Override
public void onSetCaptionEnabled(boolean enable) {}
#Override
public TvPlayer getTvPlayer() { return null; }
}
private TextView mTextView;
}
According to TvInputService.Session.notifyVideoAvailable() documentation:
The TV input service must call this method as soon as the content
rendered onto its surface is ready for viewing. This method must be
called each time onTune(Uri) is called.
So it is enough to call notifyVideoAvailable() in BaseTvInputService.Session.onTune(Uri) method override, like so:
#Override
public boolean onTune(Uri channelUri) {
notifyVideoAvailable();
return true;
}
I must say, that using the TV Companion Library's BaseTvInputService makes finding such issues harder than when using bare TvInputService, as an onTune() method is non-abstract in BaseTvInputService.Session.

How to customize Unity Dependency injection to select a different constructor as an extension

I am not in control of the registration of dependencies of my unity container and want to build an extension that allows me to select a different constructor then the default one.
So how do i do this in a builder strategy like below?
public sealed class CustomBuilderStrategy : BuilderStrategy
{
private readonly CustomBuildExtension extension;
public CustomBuilderStrategy(CustomBuildExtension extension)
{
this.extension = extension;
}
public override void PreBuildUp(IBuilderContext context)
{
//Check if type has more than one constructor
// select a random constructor and build the object. (I will write my own custom code then if this works.
base.PreBuildUp(context);
}
public override void PostTearDown(IBuilderContext context)
{
base.PostTearDown(context);
}
public override void PostBuildUp(IBuilderContext context)
{
base.PostBuildUp(context);
}
public override void PreTearDown(IBuilderContext context)
{
base.PreTearDown(context);
}
}
You can find some data regarding to overriding the object creation at:
https://weblogs.asp.net/ricardoperes/unity-part-10-custom-build-strategies
To get information about the constructors for a given type you can use reflection
typeof(type).GetConstructors()

Spring + Jackson + joda time: how to specify the serialization/deserialization format?

I have the following class:
public static class ARestRequestParam
{
String name;
LocalDate date; // joda type
}
And I want it to be deserialized from the following JSON which is processed by jackson.
{ name:"abc", date:"20131217" }
Actually, I want to deserialize any LocalDate field in any class with "yyyyMMdd" format, without duplicating the format string, without adding any setter method, without any XML configuration. (That is, annotation and Java code is preferable)
How can it be done?
Also, I also want to know the serialization part. that is, LocalDate -> "yyyyMMdd".
I've seen followings:
jackson-datatype-joda (https://github.com/FasterXML/jackson-datatype-joda)
custom serializer (public class JodaDateTimeJsonSerializer extends JsonSerializer { ... } - Spring #ResponseBody Jackson JsonSerializer with JodaTime)
#JsonCreator
#DateTimeFormat
But I don't know which is applicable, and which is most up-to-date.
BTW, I use Spring Boot.
UPDATE
Ok, I have managed to write working code for the deserialization part.
It is as follows:
#Configuration
#EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters)
{
converters.add(jacksonConverter());
}
#Bean
public MappingJackson2HttpMessageConverter jacksonConverter()
{
MappingJackson2HttpMessageConverter converter =
new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ApiJodaModule());
converter.setObjectMapper(mapper);
return converter;
}
#SuppressWarnings("serial")
private class ApiJodaModule extends SimpleModule
{
public ApiJodaModule()
{
addDeserializer(LocalDate.class, new ApiLocalDateDeserializer());
}
}
#SuppressWarnings("serial")
private static class ApiLocalDateDeserializer
extends StdScalarDeserializer<LocalDate>
{
private static DateTimeFormatter formatter =
DateTimeFormat.forPattern("yyyyMMdd");
public ApiLocalDateDeserializer() { super(LocalDate.class); }
#Override
public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (jp.getCurrentToken() == JsonToken.VALUE_STRING)
{
String s = jp.getText().trim();
if (s.length() == 0)
return null;
return LocalDate.parse(s, formatter);
}
throw ctxt.wrongTokenException(jp, JsonToken.NOT_AVAILABLE,
"expected JSON Array, String or Number");
}
}
}
I had to implement the deserializer myself, since the datetime format for the deserializer in jackson-datatype-joda cannot be altered. So, since I've implemented the deserializer myself, jackson-datatype-joda is not needed. (although I've copied pieces of its code)
Is this code Ok?
Is this up-to-date solution?
Is there any other easier way?
Any suggestion would be greatly appreciated.
UPDATE
Following Dave Syer's suggestion, I modified the source above as follows:
Removed 2 methods: configureMessageConverters(), jacksonConverter()
Added following method into WebMvcConfiguration class:
#Bean
public Module apiJodaModule()
{
return new ApiJodaModule();
}
But now it does not work. It seems apiJodaModule() is ignored.
How can I make it work?
(It seems that I should not have a class that has #EnableWebMvc to use that feature.)
The version I use is org.springframework.boot:spring-boot-starter-web:0.5.0.M6.
UPDATE
Final working version is as follows: (with other configurations I've done previously in the class that had #EnableWebMvc)
As Dave Syer mentioned, this will only work on BUILD-SNAPSHOT version, at least for now.
#Configuration
public class WebMvcConfiguration
{
#Bean
public WebMvcConfigurerAdapter apiWebMvcConfiguration()
{
return new ApiWebMvcConfiguration();
}
#Bean
public UserInterceptor userInterceptor()
{
return new UserInterceptor();
}
public class ApiWebMvcConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(userInterceptor())
.addPathPatterns("/api/user/**");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
}
#Bean
public Module apiJodaModule()
{
return new ApiJodaModule();
}
#SuppressWarnings("serial")
private static class ApiJodaModule extends SimpleModule
{
public ApiJodaModule()
{
addDeserializer(LocalDate.class, new ApiLocalDateDeserializer());
}
private static final class ApiLocalDateDeserializer
extends StdScalarDeserializer<LocalDate>
{
public ApiLocalDateDeserializer() { super(LocalDate.class); }
#Override
public LocalDate deserialize(JsonParser jp,
DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (jp.getCurrentToken() == JsonToken.VALUE_STRING)
{
String s = jp.getText().trim();
if (s.length() == 0)
return null;
return LocalDate.parse(s, localDateFormatter);
}
throw ctxt.mappingException(LocalDate.class);
}
}
private static DateTimeFormatter localDateFormatter =
DateTimeFormat.forPattern("yyyyMMdd");
}
}
Your code is OK, but if you use #EnableWebMvc in a Spring Boot app you switch off the default settings in the framework, so maybe you should avoid that. Also, you now have only one HttpMessageConverter in your MVC handler adapter. If you use a snapshot of Spring Boot you ought to be able to simply define a #Bean of type Module and everything else would be automatic, so I would recommend doing it that way.

Resources