I have a SWf application built in flex 4. One part of the application relies on accessing a public variable ("step1") set at the application root, and is accessed with
var app:Object = FlexGlobals.topLevelApplication;
trace("step one is "+app.step1);
This, while not optimal, has worked fine. Now, hoever, I need to load this entire application into another application, and I can't figure out how to access my step1 variable any longer.
I have been loading the swf into the new parent application like so:
public var myLoader:Loader = new Loader();
public var pizzaContainer:UIComponent = new UIComponent();
private var myUrl:URLRequest = new URLRequest("chickensoup.swf");
protected function application1_creationCompleteHandler(event:FlexEvent):void {
myLoader.load(myUrl);
pizzaContainer.addChild(myLoader);
addElement(pizzaContainer);
}
And I have tried using FlexGlobals.topLevelApplication.pizzaContainer to no avail. What would be the method of acessing a public variable at the root of the loaded application?
The SWF Loader has a content property which is available after the Loader Completed event has been raised, you can use this to access any exposed property in the loaded SWF
public var loadedSM:SystemManager;
// Initialize variables with information from
// the loaded application.
private function initNestedAppProps():void {
loadedSM = SystemManager(myLoader.content);
}
Now try get values referencing like this:
loadedSM.application["lblOne"].text
loadedSM.application["step1"]
Remember to make sure these are public variables!
Related
We are transitioning from Xamarin.Forms to .Net MAUI but our project uses Prism.Unity.Forms. We have a lot of code that basically uses the IContainer.Resolve() passing in a collection of ParameterOverrides with some primitives but some are interfaces/objects. The T we are resolving is usually a registered View which may or may not be the correct way of doing this but it's what I'm working with and we are doing it in backend code (sometimes a service). What is the correct way of doing this Unity thing in DryIoC? Note these parameters are being set at runtime and may only be part of the parameters a constructor takes in (some may be from already registered dependencies).
Example of the scenario:
//Called from service into custom resolver method
var parameterOverrides = new[]
{
new ParameterOverride("productID", 8675309),
new ParameterOverride("objectWithData", IObjectWithData)
};
//Custom resolver method example
var resolverOverrides = new List<ResolverOverride>();
foreach(var parameterOverride in parameterOverrides)
{
resolverOverrides.Add(parameterOverride);
}
return _container.Resolve<T>(resolverOverrides.ToArray());
You've found out why you don't use the container outside of the resolution root. I recommend not trying to replicate this error with another container but rather fixing it - use handcoded factories:
internal class SomeFactory : IProductViewFactory
{
public SomeFactory( IService dependency )
{
_dependency = dependency ?? throw new ArgumentNullException( nameof(dependency) );
}
#region IProductViewFactory
public IProductView Create( int productID, IObjectWithData objectWithData ) => new SomeProduct( productID, objectWithData, _dependency );
#endregion
#region private
private readonly IService _dependency;
#endregion
}
See this, too:
For dependencies that are independent of the instance you're creating, inject them into the factory and store them until needed.
For dependencies that are independent of the context of creation but need to be recreated for each created instance, inject factories into the factory and store them.
For dependencies that are dependent on the context of creation, pass them into the Create method of the factory.
Also, be aware of potential subtle differences in container behaviours: Unity's ResolverOverride works for the whole call to resolve, i.e. they override parameters of dependencies, too, whatever happens to match by name. This could very well be handled very differently by DryIOC.
First, I would agree with the #haukinger answer to rethink how do you pass the runtime information into the services. The most transparent and simple way in my opinion is by passing it via parameters into the consuming methods.
Second, here is a complete example in DryIoc to solve it head-on + the live code to play with.
using System;
using DryIoc;
public class Program
{
record ParameterOverride(string Name, object Value);
record Product(int productID);
public static void Main()
{
// get container somehow,
// if you don't have an access to it directly then you may resolve it from your service provider
IContainer c = new Container();
c.Register<Product>();
var parameterOverrides = new[]
{
new ParameterOverride("productID", 8675309),
new ParameterOverride("objectWithData", "blah"),
};
var parameterRules = Parameters.Of;
foreach (var po in parameterOverrides)
{
parameterRules = parameterRules.Details((_, x) => x.Name.Equals(po.Name) ? ServiceDetails.Of(po.Value) : null);
}
c = c.With(rules => rules.With(parameters: parameterRules));
var s = c.Resolve<Product>();
Console.WriteLine(s.productID);
}
}
I'm moving an existing ASP.NET/MVC app to aspnet core, and there's a bit where I'm not sure of the cleanest solution.
The issue is that we have a shared view that is called from a number of controllers. There's a chunk of html that is loaded from a file by the controller, and then is inserted into the page by the view using #Html.Raw().
The existing code in .NET Framework is using an extension method on Controller to get the contents of the file:
public static class ControllerExtension
{
public static string GetContents(this Controller controller, string path)
{
var filepath = controller.Server.MapPath(path);
var contents = System.IO.File.ReadAllText(filepath);
return contents;
}
}
This, of course, does not work in aspnet core. There is no Server.MapPath().
Googling around I found that the recommended approach is to use IWebHostEnvironment. I could do that - inject it into my controller, and pass it to my GetContents() extension, but that's starting to have a bit of a whiff about it.
So I'm wondering, is there some other mechanism for doing the basic task?
Assume I have a number of files in a directory under wwwroot, each containing plain html.
What would be the cleanest way to have a controller include the contents of one of these files in a .cshtml view?
I've used the WebRootPath property of the environment to get to wwwroot and use relative paths from there. Example:
public class MyController
{
private readonly IWebHostEnvironment environment;
public MyController(IWebHostEnvironment environment)
{
this.environment = environment ?? throw new ArgumentNullException(nameof(environment));
}
public IActionResult GetContents(string path)
{
var contentPath = Path.Combine(environment.WebRootPath, path);
var content = System.IO.File.ReadAllText(contentPath);
// Do something with content and return
}
}
You would of course want more checks to validate the user-provided path before attempting to read the file. Also, would likely make this async unless you cache the content and normally serve the memory-cached data.
My aim is to access bindable property across the the App. But My current framework ViewModel Instance create multiple time
My Requirement : I have the cart count in the bottomTray(CheckuoutViewModel) i want to increase the cart count any where in the app page, but in this cart count not update when back click, its only working on forward navigation, the reason behind CheckoutViewModel instance create each and every time. so that i'm try to instant creation at earlier.
Here I'm list out sample ViewModel and calling method
Login ViewModel
Checkuout ViewModel(This view model common for all page)
BaseNavigationViewModel(Its BaseViewModel)
As of now i'm calling when BindinContext each and every time like,
new LoginViewMode(navigation)
new CheckoutViewModel(navigation)
what will do to create all ViewModel instance when app start time like ViewModel Locator?
Im tried
public static ViewModelLocator Locator
{
get { return locator ?? (locator = new ViewModelLocator()); }
}
And ViewModel Locator
public ViewModelLocator()
{
navigation = App.Current.MainPage.Navigation;
}
internal CustomTabBarViewModel CustomTabBarVM
{
get
{
return customTabBarVM ?? (customTabBarVM = new CustomTabBarViewModel(navigation));
}
}
And CustomTabBar.xaml.cs
public CustomTabBar()
{
viewModel = App.Locator.CustomTabBarVM;
InitializeComponent();
BindingContext = viewModel;
}
and Expectation
App.Locator.CustomTabBarVM.BadgeCartCount = OrderObject.Instance.ORDER_OBJECT.Items.Count;
This approach is working fine but it's create some navigation issues
A singleton instance is a common feature of virtually all MVVM frameworks (Prism, FreshMVVM etc). If you aren't using a framework (if you aren't, I would STRONGLY advise you consider using one), below is a solution.
To obtain a single instance of a ViewModel you can use the App class to host the object and access it whenever you need.
Create a public static property of your ViewModel:
public static MyViewModel MyViewModelInstance { get; }
Create an instance in the constructor of the app
public App()
{
InitializeComponent();
MyViewModelInstance = new MyViewModel();
var myPage = new MyPage()
{
BindingContext = MyViewModelInstance
};
var navPage = new NavigationPage(myPage);
MainPage = navPage;
}
Whenever you create a new page, access the shared instance
// This method is just an example of how you might create a new page and wire up the view model
async void GoNextClicked(System.Object sender, System.EventArgs e)
{
var myPage = new MyPage()
{
BindingContext = App.MyViewModelInstance
};
await this.Navigation.PushAsync(myPage);
}
This approach comes with a few caveats, you are creating instances when the app loads not when they are needed (Eagerly loading). So a performance optimisation would be to use Lazy<T> to handle the creation of these objects. However this is logic that has already been written for you in MVVM frameworks, they are there to help you and you should be using them.
Lazy Load
You can save memory and performance at startup by lazy loading the viewmodel, here is this example rewritten to support this pattern:
public static MyViewModel MyViewModelInstance
{
get => _myViewModelInstanceFactory.Value;
}
private static Lazy<MyViewModel> _myViewModelInstanceFactory = new Lazy<MyViewModel>(() => new MyViewModel(), true);
public App()
{
InitializeComponent();
var myPage = new MyPage()
{
BindingContext = MyViewModelInstance
};
var navPage = new NavigationPage(myPage);
MainPage = navPage;
}
Now this object won't be created until it is accessed by your code, and once it has been accessed once it has already been created and will go on to live in memory for the rest of your apps lifecycle.
Axemasta has good answer about re-use of a shared view model instance.
I'll give an alternative approach to the underlying need given in one comment: how to have a static property (so the value is common), and Bind to it when Binding to an instance.
Use this approach if you do want a different CheckoutViewModel for each new page. For example, if there are other properties that should be set up differently, depending on the page.
public class CheckoutViewModel : : INotifyPropertyChanged // or your MVVM library's base class for ViewModels.
{
public static int SharedCount { get; set; }
public void IncrementCount()
{
Count = Count + 1;
}
public int Count {
get => SharedCount;
set {
// Exact code might be simpler if using an MVVM library.
if (SharedCount != value)
{
SharedCount = value;
OnPropertyChanged("Count");
}
}
}
}
}
LIMITATION: This assumes that only the current instance of CheckoutViewModel is visible; if you need to "notify" OTHER Views (update other CheckoutViewModel instances), then you'll need a "publish/subscribe" solution. In Xamarin Forms, one such solution is MessagingCenter.
I'm new to Flex and BlazeDS and I'm trying to implement a simple application which uses Flex on the front end and a Spring/Hibernate application on the back end, with communication between the two going over a BlazeDS channel.
I'm seeking direction as to the best and/or simplest way to approach this. I have the UI set up in such a way that the user is presented with a file chooser in which they pick the image file they want to upload. When this is chosen and submitted (as a form submission) then the server side should receive the image file data as well as some related metadata such as a description and date, then populate a Hibernate entity/POJO with the image file data and related metadata, and then persist the entity/POJO into the database.
I have found some examples of how you would do a file upload and download using servlets here and the FileReference class (here and here) but these don't appear to address the problem in a way which leverages BlazeDS and/or Spring/Hibernate. I want to put the image file data and related metadata (description, capture date, etc.) into a value object within the Flex application and then send this over BlazeDS to a service provided by my Spring/Hibernate application running on Tomcat. In this service I want to extract the image data (both the actual JPG/PNG/GIF data and the related metadata such as description, etc.) from the value object sent from the Flex app into an entity/POJO which is then persisted via Hibernate in my database.
Can this be done, and if so what's the best way to go about it? Am I mistaken in assuming that if I use BlazeDS then I am somehow bypassing the need to provide HTTP-based services such as servlets on the server side and instead I can use my Java services as "RemoteObjects"? Is there necessarily a one-to-one mapping between Java POJO/entity class and the Flex value object class when making this sort of transfer? If so is there a tool which creates corresponding Flex value objects from Java POJOs or vice versa.
Thanks in advance for your help, comments, suggestions, etc.
--James
Update: Some code to make this more clear:
I have this as my value object in Flex:
package valueobjects
{
import flash.utils.ByteArray;
[Bindable]
[RemoteClass(alias="com.abc.example.persistence.entity.Image")]
public class Image
{
public var id:Number;
public var captureDate:Date;
public var description:String;
public var imageData:ByteArray;
public function Image() {}
}
I am assuming that this can be used as a one-to-one mapping to the POJO class used by my service and DAO classes on the server-side, which looks like this:
package com.abc.example.persistence.entity;
import java.sql.Blob;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
#Entity(name = "IMAGE")
public class Image
extends AbstractBaseEntity<Long>
{
private String description;
private Date captureDate;
private Blob imageData;
#Column(name = "CAPTURE_DATE", nullable = true)
public Date getCaptureDate()
{
return captureDate;
}
#Column(name = "DESCRIPTION", nullable = true)
public String getDescription()
{
return description;
}
#Column(name = "IMAGE_DATA", nullable = true)
public Blob getImageData()
{
return imageData;
}
public void setCaptureDate(final Date captureDate)
{
this.captureDate = captureDate;
}
public void setDescription(final String description)
{
this.description = description;
}
public void setImageData(final Blob imageData)
{
this.imageData = imageData;
}
}
In my Flex application I populate the fields of an Image object with a description string, date, and image file data (based on the user's file selection and text input for the description) and then call a method on the RemoteObject which is mapped to the service running on Tomcat. I make the RemoteObject service call within my Flex code using the Image value object as the argument, but the service method running on the servier side actually expects an argument of the POJO/entity type, and it's here that I am thinking that some sort of conversion/transformation between the Flex value object and the Java POJO will occur (by virtue of the RemoteClass alias setting on the value object's class declaration), but it doesn't seem to be happening that way because when I debug the application the Java service is only getting null values when the service call is made.
In my Flex application I have a FileReference and Image value object as public, bindable variables:
[Bindable]
public var imageToBeArchivedFileReference:FileReference = new FileReference();
[Bindable]
public var imageToBeArchivedValueObject:valueobjects.Image = new valueobjects.Image();
There is also an event handler to browse for a file when the user clicks on a file select button:
protected function imageFileSelectButton_clickHandler(event:MouseEvent):void
{
var imageFileFilter:FileFilter = new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png");
var fileTypes:Array = new Array();
fileTypes.push(imageFileFilter);
imageToBeArchivedFileReference.addEventListener(Event.SELECT, imageToBeArchived_fileSelectHandler);
imageToBeArchivedFileReference.browse(fileTypes);
}
There is an event handler which builds the value object when the image file has been selected:
private function imageToBeArchived_fileSelectHandler(event:Event):void
{
imageToBeArchivedFileReference.load();
imageToBeArchivedValueObject = new valueobjects.Image()
imageToBeArchivedValueObject.imageData = imageToBeArchivedFileReference.data;
imageToBeArchivedValueObject.description = imageToBeArchivedDescription.text;
imageToBeArchivedValueObject.captureDate = imageToBeArchivedFileReference.creationDate;
}
and there's an event handler which is invoked when the user clicks on the submit button to perform the image save/upload:
protected function archiveImageButton_clickHandler(event:MouseEvent):void
{
imageArchivalService.archiveImage(imageToBeArchived);
}
On the server side my Java class is doing a simple save of the POJO:
public void archiveImage(final Image image)
{
imageDao.saveOrUpdate(image);
}
When I set a breakpoint in the method above and look at the image variable it looks to be empty, so I'm assuming that the transformation from the Flex value object to the Java POJO did not go as expected and that there's more to it than just adding a RemoteClass alias in the Flex value object class.
Check out this example, it is all there.
http://biemond.blogspot.com/2008/08/flex-upload-and-download-with-blazeds.html
Don't use the loader class, use the readBytes call.
Make sure you go to the comments, there are valuable info there.
Cheers
I have a dynamic ActionScript Class that is used to send parameters to a WebService. Some of these parameters are always present, so they are public properties of the Class:
package
{
[Bindable]
public dynamic class WebServiceCriteria
{
public var property1:int;
public var property2:String;
public var property3:String;
public var property4:String;
}
}
But, I am also adding properties at runtime that can change over time:
criteria.runTimeProperty = "1";
I'm not very familiar with using dynamic classes, so I was wondering if it is possible to "remove" the new property. Let's say the next time I call the WebService I don't want that property sent - not even as a null. How can I remove it from the Class instance without creating a new instance each time?
I believe all you'd need to do is this:
delete criteria.runTimeProperty;
or
delete criteria["runTimeProperty"];
Either should do the same thing.
See the delete documentation for specifics.