deriving a class from another class causes Com registration error - c#

I have a project that follows WPF/MVVM pattern. I have tried to derive my ViewModel class from PropertyChangedBase so that I can Notify of data changes to the view. As soon as I derive the class from PropertyChangeBase and compile, I get error saying
Error 1 Cannot register assembly "D:\Source\ArcOnline\bin\Debug\ArcOnline.dll". Could not load file or assembly 'Major, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
here is how my class is defined
using ArcOnline.WPF;
using System;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace ArcOnline.ViewModels
{
/// <summary>
/// The class handles the template for a single
/// </summary>
public class TemplatesViewModel : PropertyChangedBase
{
/// <summary>
///
/// </summary>
public ArcOnlineViewModel ArcManager { get; set; }
private string _layerID;
/// <summary>
/// Layer ID
/// </summary>
public string LayerID
{
get { return _layerID; }
set { _layerID = value; NotifyOfPropertyChange(() => LayerID); }
}
private string _title;
/// <summary>
/// Title of the layer
/// </summary>
public string Title
{
get { return _title; }
set { _title = value; NotifyOfPropertyChange(() => Title); }
}
............. More properties as above
}
and here is the how my PropertyChangedBase is defined
using Component.Linq.Expressions;
using System;
using System.Collections;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Runtime.Serialization;
using System.Xml.Serialization;
#endregion
namespace Component.ComponentModel
{
/// <summary>
/// A base class from which ViewModels can inherit to improve the quality of
/// patterns such as INotifyPropertyChanged.
/// </summary>
[DataContract]
[Serializable]
public class PropertyChangedBase : INotifyPropertyChanged, INotifyDataErrorInfo, IDataErrorInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertyChangedBase"/> class.
/// </summary>
public PropertyChangedBase()
{
ErrorsChanged += Notify_ErrorChanged;
}
void Notify_ErrorChanged(object sender, DataErrorsChangedEventArgs e)
{
NotifyOfPropertyChange(() => Error);
}
...... More class definition continues
}
This PropertyChangedBase is actually defined in a different Project so that is why it has all the header files included. If I copy the code of this PropertyChangedBase class and create a new class in my own Project where TemplatesViewModel is defined and then use it, it works perfectly fine.
I just want to know what is the reason for it not working in the first case?? This wasted my whole day!!
Thanks in advance

Related

Acessing COM Interop from Python

I want to acess a COM interop functionality written in c# from Python. I have the following code written in c# which defines the COM interop functionality and is compiled as a .dll and registered using regasm.exe. This seems to work fine.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ComInteropDemo
{
/// <summary>
/// implementation of the method com interface
/// </summary>
[Guid("1C9E938A-9BF5-4A42-B795-A4AC2B1E7AC0")]
[ProgId("Test.Test.ComInteropClass")]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IComInteropClass))]
[ComVisible(true)]
public class ComInteropClass : IComInteropClass
{
/// <summary>
/// Reads a text
/// </summary>
/// <param name="text">The text (as out parameter)</param>
/// <returns>true if successful</returns>
public bool ReadText(out string text)
{
text = "Hello from Com Interop";
return true;
}
/// <summary>
/// Writes a text to a file
/// </summary>
/// <param name="text"></param>
/// <returns>true if successful</returns>
public bool WriteText(string text)
{
string fileName = Path.Combine(Path.GetTempPath(), "ComInteropDemoOutput.txt");
try
{
File.WriteAllText(fileName, text);
}
catch (IOException)
{
return false;
}
return true;
}
}
}
The problem is, that I want to acess the COM interop functionality from python (client side), I try to use the comtypes library for that and I try to load the COM interop demo using the following code:
from comtypes.client import CreateObject
comobject = CreateObject("Test.Test.ComInteropClass")
Problem is, it throws an errors saying:
"AttributeError: module 'comtypes.gen.ComInteropDemo' has no attribute 'IComInteropClass'"
It seems I have to define the attribute IComInteropClass in the c# definition of the COM functionality, but I do not know how. Any help on this would be very much appreciated!

exposing .Net to COM

I have some .Net functionality I am trying to use in VB6. I have followed several tutorials. I wrote a test program with success using the formula here: http://www.codeproject.com/Articles/3511/Exposing-NET-Components-to-COM
However, when I try to do it with my actual project, my ProgId doesn't show in the registry like my test file. I made sure property ComVisible == true
using System.Runtime.InteropServices;
namespace Controls.Graph.Web
{
[Guid("5F9F6C6F-016A-4CFF-BD7A-3463761807E1")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _GraphScript
{
[DispId(1)]
string getGraphXml();
}
[Guid("35901BC6-EFF1-490C-84FA-786E8462C553")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId(ProgIds.GraphScript)]
public class GraphScript : _GraphScript
{
protected GraphScript()
{
}
/// <summary>
///
/// </summary>
/// <returns>The graphs xml and javascript</returns>
public string getGraphXml()
{
DisplayDefaults tempDefaults;
tempDefaults = new DisplayDefaults();
GraphConstructor graph = new GraphConstructor();
graph.constructGraph();
GraphModel completedGraph = graph.Graph;
return GraphControl.RenderGraph(completedGraph, tempDefaults, 1) + GraphControl.RenderGraphScript();
}
}
}
and my progid...
using System;
namespace Controls.Graph.Web
{
/// <summary>
/// ProgID Constant
/// </summary>
public static class ProgIds
{
public const string GraphScript = "GraphData";
}
}
I'm not sure which piece of the puzzle I'm missing here
EDIT: actually the Guid shows up in the registry however the Progid still is not. Any ideas/suggestions?
also made sure to do this:
I have figured out what was wrong. I needed to change some access modifiers to PUBLIC -- including my GraphScript() constructor.

Serializing a collection and comply to Code Analysis

While running Code Analysis on an existing project I came across the messages Do not expose generic lists and Collection properties should be read only.
However, this class is used to read/write from/to an xml configuration file.
Is it possible to make this class comply to CA1002 and CA2227 or do I have to suppress these rules for XML-related classes (there are a lot of them in the project)?
EDIT
Changing List<string> to Collection<string> solved CA1002.
Still no clue on how to solve CA2227 and still be able to (de)serialize the whole thing.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
/// <summary>
/// Class containing the Configuration Storage
/// </summary>
[XmlRoot("Configuration")]
public class ConfigurationStorage
{
/// <summary>
/// Gets or sets the list of executers.
/// </summary>
[XmlArray("Executers")]
[XmlArrayItem("Executer")]
public Collection<string> Executers { get; set; }
/// <summary>
/// Gets or sets the list of IPG prefixes.
/// </summary>
[XmlArray("IpgPrefixes")]
[XmlArrayItem("IpgPrefix")]
public Collection<string> IpgPrefixes { get; set; }
}
Reading the xml-file:
public static ConfigurationStorage LoadConfiguration()
{
if (File.Exists(ConfigFile))
{
try
{
using (TextReader r = new StreamReader(ConfigFile))
{
var s = new XmlSerializer(typeof(ConfigurationStorage));
var config = (ConfigurationStorage)s.Deserialize(r);
return config;
}
}
catch (InvalidOperationException invalidOperationException)
{
throw new StorageException(
"An error occurred while deserializing the configuration XML file.", invalidOperationException);
}
}
}
How about:
/// <summary>
/// Class containing the Configuration Storage
/// </summary>
[XmlRoot("Configuration")]
public class ConfigurationStorage {
/// <summary>
/// Gets or sets the list of executers.
/// </summary>
[XmlArray("Executers")]
[XmlArrayItem("Executer")]
public Collection<string> Executers { get; private set; }
/// <summary>
/// Gets or sets the list of IPG prefixes.
/// </summary>
[XmlArray("IpgPrefixes")]
[XmlArrayItem("IpgPrefix")]
public Collection<string> IpgPrefixes { get; private set; }
public ConfigurationStorage() {
Executers = new Collection<string>();
IpgPrefixes = new Collection<string>();
}
}
This will still work for xml serialization/deserialization.
If you read the documentation on MSDN, you see a note:
The XmlSerializer gives special treatment to classes that implement
IEnumerable or ICollection. A class that implements IEnumerable must
implement a public Add method that takes a single parameter. The Add
method's parameter must be of the same type as is returned from the
Current property on the value returned from GetEnumerator, or one of
that type's bases. A class that implements ICollection (such as
CollectionBase) in addition to IEnumerable must have a public Item
indexed property (indexer in C#) that takes an integer, and it must
have a public Count property of type integer. The parameter to the Add
method must be the same type as is returned from the Item property, or
one of that type's bases. For classes that implement ICollection,
values to be serialized are retrieved from the indexed Item property,
not by calling GetEnumerator.
So, I think, if you fall in line with this special treatment, you'll have better code that works with XmlSerializer, doesn't use a legacy namespace, and satisfies Code Analysis warnings in the right way, rather than exploiting an oversight in the rule.
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
/// <summary>
/// Class containing the Configuration Storage
/// </summary>
[XmlRoot("Configuration")]
public class ConfigurationStorage
{
// The executers.
private readonly ICollection<string> executers = new List<string>();
// The IPG prefixes.
private readonly ICollection<string> ipgPrefixes = new List<string>();
/// <summary>
/// Gets the list of executers.
/// </summary>
[XmlArray("Executers")]
[XmlArrayItem("Executer")]
public ICollection<string> Executers
{
get
{
return this.executers;
}
}
/// <summary>
/// Gets the list of IPG prefixes.
/// </summary>
[XmlArray("IpgPrefixes")]
[XmlArrayItem("IpgPrefix")]
public ICollection<string> IpgPrefixes
{
get
{
return this.ipgPrefixes;
}
}
}

SDL Tridion EventSubscription UnSubscribe Issue

We are trying to Unsubscribe from the eventSubscripton in our Eventing Code. We are using the following code
[TcmExtension("EventHandlerExtension")]
public class EventHandler : TcmExtension, IDisposable
{
private EventSubscription componentSaveSubscription = null;
private EventSubscription componentPublishSubscription = null;
#region Public Methods
/// <summary>
/// Handle for Eventing System
/// </summary>
public EventHandler()
{
Subscribe();
}
/// <summary>
/// Subscribe Events
/// </summary>
public void Subscribe()
{
//News Article Page created when component Save
componentSaveSubscription = EventSystem.Subscribe<Component, SaveEventArgs>(OnComponentSavePost, EventPhases.TransactionCommitted);
//EventSystem.Subscribe<Component, SaveEventArgs>(OnComponentSavePost, EventPhases.TransactionCommitted);
componentPublishSubscription = EventSystem.Subscribe<Component, PublishOrUnPublishEventArgs>(OnComponentPublishOrUnPublishPost, EventPhases.TransactionCommitted);
//EventSystem.Subscribe<StructureGroup, PublishOrUnPublishEventArgs>(OnStructureGroupPublishInitiated, EventPhases.TransactionCommitted);
}
/// <summary>
/// IDisposable Implementation
/// </summary>
public void Dispose()
{
if (componentSaveSubscription != null) componentSaveSubscription.Unsubscribe();
if (componentPublishSubscription != null) componentPublishSubscription.Unsubscribe();
}}
What we have observed is that once “{EventSubsciption}.Unsubscribe” is called, eventing stops working for the subsequent events for which it is supposed to work. Once the event system related services are restarted, the eventing code works as expected for the first time only and never gets called for subsequent events(for which it was supposed to work).
Try removing the Dispose method and see if that makes a difference. It's possible that Tridion instantiates the Event Handler upon the first instance of an event being fired, and then never does it again until the system is restarted. So if you unsubscribe and dispose, then your class won't be instantiated again. It's also possible that something else in your environment is interfering. Hard to say, but try by removing the Dispose first.
My boilerplate Handler looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Tridion.ContentManager;
using Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.ContentManagement.Fields;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.Extensibility.Events;
namespace NicksEventSystem
{
[TcmExtension("NicksEventSystemExtension")]
public class NicksEventHandler : TcmExtension
{
public NicksEventHandler()
{
Subscribe();
}
private void Subscribe()
{
EventSystem.Subscribe<Component, FinishActivityEventArgs>(MyEvent, EventPhases.TransactionCommitted);
}
private void MyEvent(Component wfComponent)
{
//... Do stuff!
}
}
}

C# - Intercepting property changes in subclasses

I'm in the process of creating a framework in which I provide the base class and the implementers of the framework will inherit from the base class and provide additional properties and methods. In the base class, I would like to have a way of observing when a property value is changed. The property can be from the base class or in any of the subclasses. I know that through reflection, I can determine the list of properties from any instance, but is there a way I can track the property changing value?
Here is a very simplistic example of what I am saying:
public class BaseClass
{
public string BaseClassProperty { get; set; }
public void DoSomethingWhenEitherPropertyGetsChanged()
{
}
}
public class SubClass : BaseClass
{
public string SubClassProperty { get; set; }
}
What can I do to have DoSomethingWhenEitherPropertyGetsChanged get executed when either of the properties has it's value changed.
You can use notifypropertyweaver for this purpose. It does exactly what you want. Here's a link:
notifypropertyweaver
From the open source home page:
Uses IL weaving (via http://www.mono-project.com/Cecil) to inject INotifyPropertyChanged code into properties.
No attributes required
No references required
No base class required
Supports .net 3.5, .net 4, Silverlight 3, Silverlight 4, Silverlight 5 and Windows Phone 7
Supports client profile mode
I would probably use Postsharp and create an inherited attribute injecting interception code into all public properties. Marking the attribute as inherited should also attach it to all subclasses automatically.
I wrote my own idea of your requirements, but I am not sure if it suits your needs. INotifyProperty changed is something you could also look into, but I don't really like it because it is like wiring up speghetti. Maybe this will give you some creative ideas, though.
What this does, is allow you to use ObservableObject as for all of your properties types. By doing this, each property will have an ObjectChanged event you can wire-up to. The con(s) are that you must initialize all of your properties in the constructor to prevent a NullReferenceException somewhere in your code.
This example uses three classes.
ObservableObject.cs
Employee.cs
Program.cs
ObservableObject.cs
//-----------------------------------------------------------------------------
// <copyright file="ObservableObject.cs" company="DCOM Productions">
// Copyright (c) DCOM Productions. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------
namespace PropertyChangedEventExample {
using System;
public class ObservableObject : Object {
/// <summary>
/// Expose the default constructor
/// </summary>
public ObservableObject() {
// No default implementation
}
private object m_Object = null;
/// <summary>
/// Base object
/// </summary>
public object Object {
get {
return m_Object;
}
set {
if (m_Object != value) {
m_Object = value;
OnObjectChanged(this, EventArgs.Empty);
}
}
}
/// <summary>
/// Triggered when the value of this object has changed.
/// </summary>
public event System.EventHandler<EventArgs> ObjectChanged;
/// <summary>
/// EventHandler wire-up
/// </summary>
protected virtual void OnObjectChanged(object sender, System.EventArgs e) {
if (ObjectChanged != null) {
ObjectChanged(sender, e);
}
}
/// <summary>
/// Gets the value
/// </summary>
public object Get() {
return this.Object;
}
/// <summary>
/// Sets the value
/// </summary>
public void Set(object value) {
this.Object = value;
}
}
}
Employee.cs
//-----------------------------------------------------------------------------
// <copyright file="Employee.cs" company="DCOM Productions">
// Copyright (c) DCOM Productions. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------
namespace PropertyChangedEventExample {
using System;
public class Employee {
/// <summary>
/// Expose default constructor
/// </summary>
public Employee() {
Name = new ObservableObject();
}
/// <summary>
/// Gets or sets the name
/// </summary>
public ObservableObject Name {
get;
set;
}
}
}
Program.cs
//-----------------------------------------------------------------------------
// <copyright file="Program.cs" company="DCOM Productions">
// Copyright (c) DCOM Productions. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------
namespace PropertyChangedEventExample {
using System;
class Program {
static void Main(string[] args) {
Employee employee = new Employee();
employee.Name.Set("David");
employee.Name.ObjectChanged += new EventHandler<EventArgs>(Name_ObjectChanged);
employee.Name.Set("Dave");
Console.ReadKey(true);
}
static void Name_ObjectChanged(object sender, EventArgs e) {
ObservableObject employee = sender as ObservableObject;
Console.WriteLine("Name changed to {0}", employee.Get());
}
}
}
Your best bet would be what CrisWue recommended and use postsharp or some other post-processor to inject the behavior in your properties. Other than that I think you would need to call DoSomethingWhenEitherPropertyGetsChanged() manually within your properties.
If you are creating a library that is consumed by people other than you or your organization, a post-processor may not be the right way to go as it adds the 3rd party tool as another requirement to their build process.

Categories