ASP.NET MEF Compose all class parts - asp.net

// In Global asax
DirectoryCatalog catalog = new DirectoryCatalog(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"));
CompositionContainer container = new CompositionContainer(catalog);
// do not want to compose at every instance when use Import attribute.
container.ComposeParts(this);
// add all external library (.dll)
container.ComposeParts(container);
// Index.aspx page
public partial Index: Page{
[Import]
private c1 object1;
protected void OnLoadPage
{
if (object1== null)
thrown Error("mef failed, why")
}
}
// External library Library1
[Export(typeOf(c1))]
public class c1{}
// External library Library2
[Export(typeOf(c2))]
public class c2{}
why object1 is null?
How to compose all classes from Global asax or simple to make some asp.net bootstrap lazy loading?
I do not want in every constructor to compose part. How to make all assembly or classes to be compose at the beginning in Global asax? All my [Export] are in external library classes. Main site project have reference to all .dll projects.
I am not sure the my question is correct, sorry for that.
Project is simple asp.net (no MVC) with external library with user controls.

Related

Access objects instantiated in Flex app's MXML file in other AS classes

I've got an object declared and instantiated in my Flex application's singular MXML file:
public var CDN:CDNClass = new CDNClass;
I would like to access this same CDN object (and its public methods and properties) in another class declared in a separate .as file as such:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
But when I try to access the public method parsePlayList in the CDN object in a method in the class defined in the .as file, I get the following error:
Access of undefined property CDN
The reason I want to do this is to break up the logic of my application into multiple AS files and have minimal MXML files, probably only one.
Thanks - any help is much appreciated. Perhaps my OOD/OOP thinking is not correct here?
IT depends on your class architecture. For your code to work, the CDNClass instance must be defined and implemented inside your SyncConnectorManager.
Generally, you can always call down into components, but should never call up
One option is to pass the instance ofCDNClass to a variable inside SyncConnectorManager. Add this variable to your SyncConnectionManager class:
public var CDN:CDNClass = new CDNClass;
And at some point do this:
syncConnectorManagerInstance.CDN = CDN;
That way both classes will have access to the same CDN instance and can call methods on it.
Yes, your OOP thinking is not correct here. You should take in mind differences between classes and instances. This line declares a filed in a current class and initiates it with an instance:
public var CDN:CDNClass = new CDNClass;
So current instance of your MXML class (you can think about it as usual AS class with some other notation) has public field. To operate with CDN instance you need something from the following:
Read the value of CDN (as far as it is public) from the instance of your MXML class. You need some reference to it for that.
The instance of your MXML class can have a reference to the instance of SyncConnectorManager and SyncConnectorManager should have a way to inject the value of CDN there. Something like:
Your class:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private var CDN:CDNClass;
public function SyncConnectorManager(CDN:CDNClass)
{
this.CDN = CDN;
}
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
In your case SyncConnectorManager class hasn't CDN declared (the problem of the compiler error you mentioned) and instantiated (the problem of NPE even if you just declare field).
As the bottom line I can suggest you to follow ActionScript naming and coding conventions to talk other people and team members about your code :)

Dependency inject IOrchardServices into aspx codebehind constructor

The team and I are looking at Orchard to use as our CMS. We have a fairly large ASP.NET 4.0 WebForms app and we can only migrate the bits one piece at a time. With that in mind, we will still serve our aspx pages and slowly convert them into the CMS as time allows.
I've noticed on the docs # orchardproject.net/docs, link here, about how one does authorization inside a module. So all that has to be done is include IOrchardService in the constructor of a controller and it'll get injected at runtime.
public AdminController(IMyService myService, IOrchardServices orchardServices) {
_myService = myService;
Services = orchardServices;
}
Because the conversion process will be slow, ¿can I provide a constructor with the IOrchardServices on a System.Web.UI.Page subclass?
// something like this
public partial class Test : System.Web.UI.Page
{
IOrchardServices _service;
public Test(IOrchardServices orchardServices)
{
_service = orchardServices;
}
}
This does not work, throws an exception expecting a default constructor. If I place the default constructor, the page loads correctly but IOrchardServices is not injected. ¿Is this even possible?

Calling methods in App_Code from an ASP.NET Custom Control

I am using VS2008 and have a solution file which contains 1 Website and 1 Class Library Project.
The Class Library is a Custom Control which derives from Label. The Website contains a reference to the control - it builds successfully and the compiled .dll gets added to the Website's /bin folder. I can then use it in any of the website's .aspx pages without error.
What I cannot do, however, is reference any of the Website's data access methods that are in static classes in /App_Code from within the custom control.
I don't want to repeat the website data access logic all over again within the custom control when I know it will already exist in the website - I just want to be able to call a method from a class in /App_Code . If I try and reference anything in /App_Code from within the Class Library, it fails to build and says it can't find the Namespace or that it doesn't exist in the current context.
How can I achieve this so that the Custom Control builds as a standalone control, but can make use of classes in the website it gets used in? Delegates, possibly? Was hoping it might be more straightforward than that.
EDIT: I should add that the reason the control is in a separate Class Library is so that I can include JavaScript as an embedded resource within the Control. So when it's used in a .aspx page, it adds a WebResource.axd? style link to the page instead of a load of plaintext JavaScript in the <head> section.
EDIT 2:
In the website App_Code folder, I have a static class that handles data access (snippet):
[DataObject]
public static class DBAccess
{
[DataObjectMethod(DataObjectMethodType.Select)]
public static DataTable GetSomeData(Int32 SomeParam, DateTime OtherParam)
{
SqlConnection cn = SqlLibrary.GetConnection(DBConnectionString);
DataTable _dt;
SqlLibrary.SProcFill(out _dt, cn, "usp_SomeData_Select", SomeParam, OtherParam);
return _dt;
}
}
In the Class Library's custom control (which I want to build independently of the website's existence, yet be capable of calling its methods when used as a control in an .aspx page):
namespace MyCustomControls
{
public class StatusControl : Label
{
private Int32 _someProperty = -1;
private DateTime _otherProperty = DateTime.Now;
public StatusControl()
{
//some constructor logic
}
public void FetchData()
{
//what I'd **like** to do here is:
DBAccess.GetSomeData(_someProperty, _otherProperty);
//...but DBAccess isn't "visible" to this control at build time
}
}
}

How do you access the public properties and methods of a loaded SWF

How would you go about calling the public properties and methods of a SWF you load in actionscript?
I have been using stackoverflow for years to answer my programming questions so I wanted to give back by writing a guide to an issue I had a lot of trouble figuring out. This is my first user guide so tell me if there is anything I can do to improve it.
One of the more powerful features of the flash engine is the ability to load flash programs within flash programs, through the use of the Loader class. Unfortunately communication with the loaded program is limited. While you can establish a LocalConnection object there is a limit to the traffic it can safely support.
A simple solution is to load the SWF file within your main program’s security domain. This has the benefit of exposing the public methods and properties of the loaded SWF to the loader and vice versa.
First extend the Loader class this class will be used to interact with the loaded file.
public class ParentChildLoader extends Loader
Next we must store the SWF file as a ByteArray. The variable path is a file path on the system. You could use a URLStream object instead of a FileStream for a http url.
var swfBytes:ByteArray = new ByteArray();
var file:File = new File(path);
if (file.exists)
{
var loadStream:FileStream = new FileStream();
loadStream.open(file, FileMode.READ);
loadStream.readBytes(swfBytes);
loadStream.close();
}
Now that we have the SWF stored as a ByteArray, we load the SWF into our security domain and listen for the complete event.
var context:LoaderContext = new LoaderContext();
context.allowLoadBytesCodeExecution = true;
addEventListener(Event.COMPLETE, onSwfLoad);
loadBytes(swfBytes, context);
If you want to access the loaded SWF’s properties from the loader use the content property.
Object(this.content).foo(bar);
Object(this.content).a = b;
If you want to access the loader’s public properties from the SWF use the parent property.
Object(this.parent).foo(bar);
Object(this.parent).a = b;
This has many practical applications from allowing re-usability of common functions to taking some of the programming load off your creative team. A note of caution; the loaded SWF exists within your main program’s security domain so it is key that you only load files which you trust with this method.
A cleaner way would be to use interfaces. Here's an example. Consists of two projects. Project 1 (PluginLoader) is your base app. Part of this project includes an AS3 Interface:
/* IPlugin.as */
package
{
public interface IPlugin
{
function getID():String;
function doStuff():void;
}
}
Then, your loaded swf in a second project (TestPlugin) implements the interface:
package
{
import flash.display.Sprite;
public class TestPlugin extends Sprite implements IPlugin
{
private const _ID:String = "TestPlugin";
public function getID():String {
return _ID;
}
public function doStuff():void {
trace('Test plugin: Doing Stuff');
}
}
}
The interface would be included in that project via source files or swc.
Then to load it (back in PluginLoader project):
public class PluginLoader extends Sprite
{
public function PluginLoader()
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loader.load(new URLRequest('plugins/TestPlugin.swf'));
}
private function completeHandler(e:Event):void {
var plugin:IPlugin = e.target.content as IPlugin;
trace(plugin.getID());
plugin.doStuff();
}
}
}
I would have to disagree with you on your approach. It is 'hackish' in my opinion. There is a reason why you have limited communication with loaded swfs, and that is because you don't know what they do and how they're suppose to be managed.
If you want to talk architecturally, this is a very bad way of trying to access information. The main application should not have to access properties within the loaded swf. If you're building a large scale application and the loaded swf (a module maybe?) needs information that the main app has, you should look into an application framework like Parsley which does dependency injection to give the data your loaded swf needs. It is a much cleaner approach and is architecturally sound.

Create Plugins in Flex - loading nested SWF files

I'm trying to implement a plugin system for our application, and having a devil of a time getting SWF file which was dynamically loaded itself, load additional SWF files.
It goes something like this:
Main Application Shell loads...
---------+ Application loads...
-----------------+Plugin(s)
I have no problem getting app #1 to load app #2
However, try as I might, I cannot get app #2 to load and instantiate #3
I've tried various permutations using the ModuleManager, but this is the closest I get. When the onLoadComplete method get invoked, I can see that the SWF loaded, however the factory always returns NULL.
What is interesting is that when I extract this out in its own application, it works fine. This issue is triggered by the fact that I'm loading Plugin from a SWF that was loaded dynamically itself.
I believe this is due to the ApplicationDomain, but I cannot make heads or tails of it. I tried specifying currentDomain, new ApplicationDomain(Application.currentDomain) and new ApplicationDomain() without success.
Also, it is important to note that I cannot make reference a hard reference to the Foo class in either applications since by their nature, we will not know ahead of time what they will contain.
Googlin' around, this seems to be a fairly known problem, but I have not found a (clear) solution yet.
.
.
.
assetModule = ModuleManager.getModule("Foo.swf");
assetModule.addEventListener(ModuleEvent.READY, onLoadComplete );
assetModule.addEventListener(ModuleEvent.ERROR, onLoadError);
assetModule.load();
.
.
.
private var _pluginInstance:Plugin;
private function onLoadComplete( event:Event ):void
{
trace("module loaded");
_pluginInstance = assetModule.factory.create() as Plugin;
if( _pluginInstance )
_pluginInstance.startup();
else
Alert.show("unable to instantiate module");
}
private function onLoadError( event:Event ):void
{
Alert.show("error");
}
My Plugin looks like this:
package
{
import mx.collections.ArrayCollection;
import mx.modules.ModuleBase;
public class Plugin extends ModuleBase
public function startup():void
{
}
.
.
.
}
and
package
{
import Plugin;
import mx.modules.ModuleBase;
public class Foo extends Plugin
{
public function Foo()
{
trace("foo constructor invoked");
}
override public function startup():void
{
trace("foo started");
}
.
.
.
}
# joshtynjala is right. I found try just using Object then calling methods on it (don't cast).
var MyPlugin : Object = getPlugin();
MyPlugin.doPluginFunc();
Generally can cast between system/flex classes no problem. Don't know if putting Plugin as a runtime library would help ?
If you really want to use a common interface between your plugin and your application, your application's Plugin class must be the same as your plugin's Plugin class. To do so, they need b to be in the same ApplicationDomain.
//In an external library
public interface Plugin {}
//In your application
_pluginInstance = assetModule.factory.create() as Plugin;
...
//In your plugin
public class MyPlugin implements Plugin
The problem is, when you will compile your plugin swf, you will also compile Plugin. This is not a problem, but you need to tell your application that it's the same as his :
var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));
ApplicationDomain.currentDomain is the key here. If you refer to the docs :
Loader's own ApplicationDomain. You
use this application domain when using
ApplicationDomain.currentDomain. When
the load is complete, parent and child
can use each other's classes directly.
If the child attempts to define a
class with the same name as a class
already defined by the parent, the
parent class is used and the child
class is ignored.

Resources