Access Violation - Associative Array - associative-array

I get an access violation error at this:
classes[newClass.name] = newClass;
Full method code:
void initClass(Class newClass) {
synchronized {
auto classes = cast(Class[string])classDeclarations;
classes[newClass.name] = newClass;
classDeclarations = cast(shared(Class[string]))classes;
}
}
classDeclarations is declared as this:
private shared Class[string] classDeclarations;
It has worked at earlier state in my program though. Is it possible that the access violation is due to members of newClass or is it because of class. I know it usually would occure during invalid memory access, but shouldn't the casts throw the exception too?
Am I missing something?
newClass is not null, but it's declared as following:
class Class : Variable {
private:
bool hasInit = false; // when constructor is called this is set to true ...
public:
Class[string] bases;
Variable[string] variables;
Task[string] tasks;
string typeName; // class name, not var name ...
Task constructor;
Task destructor;
this() {
super(VariableType.Class);
}
void setBaseData(Class baseClass) {
foreach (var; baseClass.variables.values) {
variables[var.name] = var;
}
foreach (task; baseClass.tasks.values) {
tasks[task.name] = task;
}
}
override bool isNull() {
return hasInit;
}
override Class copy() {
auto newClass = new Class;
newClass.typeName = typeName;
foreach (b; bases.values) {
auto newBase = b.copy();
newBase.name = b.name;
newClass.bases[newBase.name] = newBase;
}
foreach (v; variables.values) {
newClass.variables[v.name] = v.copy();
}
foreach (t; tasks.values) {
newClass.tasks[t.name] = t.copy();
}
newClass.typeName = typeName;
newClass.mutable = mutable;
newClass.constructor = constructor.copy();
newClass.destructor = destructor.copy();
return newClass;
}
override int sizeOf() {
int res = 0;
foreach (b; bases.values)
res += b.sizeOf();
foreach (v; variables.values)
res += v.sizeOf();
return res;
}
}
I was thinking it might be some of the members of Class? I have no idea though, to be honest.
initClass is called like this and all the data is initialized.
auto newClass = new Class;
newClass.name = tokenizer.name;
newClass.typeName = tokenizer.name;
foreach (base; tokenizer.baseNames) {
if (classExists(base)) {
auto baseClass = getNewClass(base);
baseClass.name = base;
newClass.bases[base] = baseClass;
newClass.setBaseData(baseClass);
}
}
initClass(newClass);
I hope to resolve this. In case I resolve it myself, I'll post it either as an answer or comment.
Thanks a lot.

The actual issue was 2 members of the Class class which were null. I was trying to access them somewhere else. The reason I thought it was related to the adding was simply that I didn't call the class that other place when it wasn't added to the collection.

Related

Mono.Cecil AddInterfaceImplementation equivalent?

I am working on Mono.Cecil codegen util, and I want to preform following operation:
Loop through types
If type contains X attribute:
- Add ITestInterface implementation (where ITestInterface has defined some methods)
// For reference
public interface ITestInterface
{
void Something();
int IntSomething();
}
// Expected result, if type contains X attribute:
// Before codegen:
[X]
public class CodeGenExample
{
}
// After codegen
[X]
public class CodeGenExample : ITestInterface
{
public void Something()
{
// some stuff
}
public int IntSomething()
{
// do some stuff
return 0;
}
}
I have seen that .NET Reflection has a AddInterfaceImplementation method (https://learn.microsoft.com/pl-pl/dotnet/api/system.reflection.emit.typebuilder.addinterfaceimplementation?view=net-5.0).
Is there a Mono.Cecil equivalent or a workaround for this & how to use it?
That can be achieved by:
Iterating over all types defined in the assembly
Checking which types have the attribute applied to
Injecting the methods.
As an example you can do something like:
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace inject
{
interface IMyInterface
{
int Something();
}
class MarkerAttribute : Attribute {}
[Marker]
class Foo
{
}
class Program
{
static void Main(string[] args)
{
if (args.Length == 1)
{
using var a = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var interfaceToImplement = a.MainModule.GetType("inject.IMyInterface");
foreach(var t in a.MainModule.Types)
{
if (t.HasCustomAttributes && t.CustomAttributes.Any(c => c.Constructor.DeclaringType.Name == "MarkerAttribute"))
{
System.Console.WriteLine($"Adding methods to : {t}");
var something = new MethodDefinition("Something", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, a.MainModule.TypeSystem.Int32);
something.Body = new Mono.Cecil.Cil.MethodBody(something);
var il = something.Body.GetILProcessor();
il.Emit(OpCodes.Ldc_I4, 42);
il.Emit(OpCodes.Ret);
t.Methods.Add(something);
// Add the interface.
t.Interfaces.Add(new InterfaceImplementation(interfaceToImplement));
var path = typeof(Program).Assembly.Location + ".new";
a.Write(path);
System.Console.WriteLine($"Modified version written to {path}");
}
}
}
else
{
object f = new Foo();
IMyInterface itf = (IMyInterface) f;
System.Console.WriteLine($"Something() == {itf.Something()}");
}
}
}
}
Another potential solution is to have the methods implemented in an internal class and copying over their method bodies.
As a side note, these are 2 online tools you can use to explore/learn more about CIL, Mono.Cecil, C#:
Sharplab.io
Cecilifier (disclaimer: I'm the author of this one)
That being said if you can use C# 9.0 you may be able to leverage the new Source Generators feature.

How to retrieve attributes from a classDeclaration with reflection

I want to create a custom attribute that will be applied to classDeclarations. I can enumerate attributes from other methods on the class, but not the classDeclaration itself because it is some sort of special method.
I know it is possible though because SysObsoleteAttribute (called from the kernel) is placed in classDeclarations all over.
In Classes\CustCustomerService\create I just copied the attributes to Classes\CustCustomerService\classDeclaration at the top for this test.
[AifDocumentCreateAttribute, SysEntryPointAttribute(true)]
class CustCustomerService extends AifDocumentService
{
}
I created a static method on a new class:
static public void AttribsOfSysEntryPointAttributeOnMethod
(
str _sNameOfClass,
str _sNameOfMethod,
str _nameOfAttribute
)
{
int nClassId;
SysDictMethod sdm;
Object attributeAsObject;
SysDictClass sysDictClass;
Array attribArray = new Array(Types::Class);
int i;
nClassId = Global::className2Id(_sNameOfClass);
sysDictClass = new SysDictClass(nClassId);
sdm = new SysDictMethod(UtilElementType::ClassInstanceMethod, nClassId, _sNameOfMethod);
attribArray = sdm.getAllAttributes();
if (attribArray)
{
for (i=1; i<=attribArray.lastIndex(); i++)
{
attributeAsObject = attribArray.value(i);
info(strFmt("[%3] Attrib Class Id: %1 [%2]", classIdGet(attributeAsObject), classId2Name(classIdGet(attributeAsObject)), _sNameOfMethod));
}
}
else
{
// Unable to get attributes, try another way
error(strFmt("Unable to retrieve attribute array for method %1", sdm.name()));
// It is, so let's try and enumerate ALL attributes and output them directly from class dec
sdm = sysDictClass.objectMethodObject(1);
if (attribArray)
{
for (i=1; i<=attribArray.lastIndex(); i++)
{
attributeAsObject = attribArray.value(i);
info(strFmt("[%3] Attrib Class Id: %1 [%2]", classIdGet(attributeAsObject), classId2Name(classIdGet(attributeAsObject)), _sNameOfMethod));
}
}
else
error(strFmt("Still unable to retrieve attribute array for method %1", sysDictClass.objectMethod(1)));
}
}
Then created a job to call it, and you can see how it works for one method, but not the other.
static void Job5(Args _args)
{
AttributeReflection::AttribsOfSysEntryPointAttributeOnMethod("CustCustomerService", "create", "SysEntryPointAttribute");
AttributeReflection::AttribsOfSysEntryPointAttributeOnMethod("CustCustomerService", "classDeclaration", "SysEntryPointAttribute");
}
Any ideas how to enumerate Attributes from the classDeclaration??
The classDeclaration is not a method and cannot be called. Hence your sysDictClass variable is null.
Googling reveals that the getAllAttributes method exits on DictClass:
attribArray = sdm ? sdm.getAllAttributes() : sysDictClass.getAllAttributes();

Read and write to ASP.NET cache from static method

I have a static method in a helper class named helper.getdiscount(). This class is ASP.NET frontend code and used by UI pages.
Inside this method I check if some data is in the ASP.NET cache then return it, otherwise it makes a service call and store the result in the cache and then returns that value.
Will this be a problem considering multiple threads might be accessing it at the same time?
if (HttpContext.Current.Cache["GenRebateDiscountPercentage"] == null)
{
IShoppingService service = ServiceFactory.Instance.GetService<IShoppingService>();
rebateDiscountPercentage= service.GetGenRebateDiscountPercentage().Result;
if (rebateDiscountPercentage > 0)
{
HttpContext.Current.Cache.Add("GenRebateDiscountPercentage", rebateDiscountPercentage, null, DateTime.Now.AddDays(1), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
}
}
else
{
decimal.TryParse(HttpContext.Current.Cache["GenRebateDiscountPercentage"].ToString(), out rebateDiscountPercentage);
}
Please advise if this is fine or any better approach could be used.
try something like this with lock object.
static readonly object objectToBeLocked= new object();
lock( objectToBeLocked)
{
if (HttpContext.Current.Cache["GenRebateDiscountPercentage"] == null)
{
IShoppingService service = ServiceFactory.Instance.GetService<IShoppingService>();
rebateDiscountPercentage= service.GetGenRebateDiscountPercentage().Result;
if (rebateDiscountPercentage > 0)
{
HttpContext.Current.Cache.Add("GenRebateDiscountPercentage", rebateDiscountPercentage, null, DateTime.Now.AddDays(1), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
}
}
else
{
decimal.TryParse(HttpContext.Current.Cache["GenRebateDiscountPercentage"].ToString(), out rebateDiscountPercentage);
}
}
Also you can look into following thread.
What is the best way to lock cache in asp.net?
Use these generic methods to use the cache for any type:
`public static void AddCache(string key, object Data, int minutesToLive = 1440)
{
if (Data == null)
return;
HttpContext.Current.Cache.Insert(key, Data, null, DateTime.Now.AddMinutes(minutesToLive), Cache.NoSlidingExpiration);
}
public static T GetCache<T>(string key)
{
return (T)HttpContext.Current.Cache.Get(key);
} `
Now to solve your problem:
`if(GetCache<decimal>("GenRebateDiscountPercentage") == null)
{
IShoppingService service = ServiceFactory.Instance.GetService<IShoppingService>();
rebateDiscountPercentage= service.GetGenRebateDiscountPercentage().Result;
if (rebateDiscountPercentage > 0)
{
AddCache("GetGenRebateDiscountPercentage", rebateDiscountPercentage);
}
}
else
{
rebateDiscountPercentage = GetCache<decimal>("GetGenRebateDiscountPercentage");
}
`

How to dynamically set a property of a class without using reflection (with dynamic) in C# 4 when property name is coming from another source

I'm building/updating an EntityFramework EntityObject on runtime. I want to set the properties of the entity class, property names and values are coming from another source.
So I'm doing this;
public static EntityCollection<T> UpdateLocaleEntity<T>(EntityCollection<T> entityCollectionToUpdate, params ILocaleControl[] values) where T : EntityObject
{
foreach (var x in entityCollectionToUpdate)
{
Type t = typeof(T);
dynamic localeEntity = x;
string cultureCode = localeEntity.CultureCode;
for (int j = 0; j < values.Length; j++)
{
var value = values[j].GetLocaleValue(cultureCode);
t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);
}
}
return entityCollectionToUpdate;
}
So, how can I get rid of "t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);" part, is there a dynamic way of doing this?
Something like;
dynamicCastedLocaleEntity.GetProperty(values[j].EntityPropertyName) = value;
Thanks.
Long answer coming up.
Reflection is great in many situations, horrible in some but in almost all cases it's slow.
There are at least 4 different ways to set a property in .NET without having to use reflection.
I thought I demonstrate one of them: Using compiled expression trees. Note that the expression building is rather expensive too so that's why it's very important to cache the delegate one builds with it in a dictionary (for instance):
Expression Trees was introduced in .NET35 and is used for many things. Here I use them to build a property setter expression and then compile it into a delegate.
The example demonstrates different timing for the different cases but here are my numbers:
Control case (hard coded): 0.02s
Reflection: 1.78s
Expression Tree: 0.06s
using System;
using System.Linq.Expressions;
namespace DifferentPropertSetterStrategies
{
class TestClass
{
public string XY
{
get;
set;
}
}
class DelegateFactory
{
public static Action<object, object> GenerateSetPropertyActionForControl(
)
{
return (inst, val) => ((TestClass) inst).XY = (string) val;
}
public static Action<object, object> GenerateSetPropertyActionWithReflection(
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
return (inst, val) => propertyInfo.SetValue (inst, val, null);
}
public static Action<object,object> GenerateSetPropertyActionWithLinqExpression (
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
var propertyType = propertyInfo.PropertyType;
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var valueParameter = Expression.Parameter(typeof(object), "value");
var lambda = Expression.Lambda<Action<object, object>> (
Expression.Assign (
Expression.Property (Expression.Convert (instanceParameter, type), propertyInfo),
Expression.Convert(valueParameter, propertyType)),
instanceParameter,
valueParameter
);
return lambda.Compile();
}
}
static class Program
{
static void Time (
string tag,
object instance,
object value,
Action<object, object > action
)
{
// Cold run
action(instance, value);
var then = DateTime.Now;
const int Count = 2000000;
for (var iter = 0; iter < Count; ++iter)
{
action (instance, value);
}
var diff = DateTime.Now - then;
Console.WriteLine ("{0} {1} times - {2:0.00}s", tag, Count, diff.TotalSeconds);
}
static void Main(string[] args)
{
var instance = new TestClass ();
var instanceType = instance.GetType ();
const string TestProperty = "XY";
const string TestValue = "Test";
// Control case which just uses a hard coded delegate
Time(
"Control",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionForControl ()
);
Time(
"Reflection",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithReflection (instanceType, TestProperty)
);
Time(
"Expression Trees",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithLinqExpression(instanceType, TestProperty)
);
Console.ReadKey();
}
}
}
For FuleSnabel's answer, you can speed it up a lot (sometimes twice as fast in my tests). In some tests, it was just as fast as the Control solution:
public static Action<Object,Object> GenerateSetPropertyActionWithLinqExpression2(Type type, String property) {
PropertyInfo pi = type.GetProperty(property,BindingFlags.Instance|BindingFlags.Public);
MethodInfo mi = pi.GetSetMethod();
Type propertyType = pi.PropertyType;
var instance = Expression.Parameter(typeof(Object), "instance");
var value = Expression.Parameter(typeof(Object), "value");
var instance2 = Expression.Convert(instance, type);
var value2 = Expression.Convert(value, pi.PropertyType);
var callExpr = Expression.Call(instance2, mi, value2);
return Expression.Lambda<Action<Object,Object>>(callExpr, instance, value).Compile();
}
possibly not with EntityObject, but if you've had an ExpandoObject than you can do
dynamic entity = new ExpandoObject();
(entity as IDictionary<String, Object>)[values[j].EntityPropertyName] = value
The open source framework ImpromptuInterface has methods to invoke based on a string using the DLR rather than reflection and runs faster than reflection too.
Impromptu.InvokeSet(localeEntity, values[j].EntityPropertyName,value);
I'm afraid not. Any use of a dynamic object is baked-in at compile time. Any call which could vary at run-time has to be done using reflection.

To check if an object is empty or not

I want to check in my function if a passed argument of type object is empty or not. Sometimes it is empty but still not null thus I can not rely on null condition. Is there some property like 'length'/'size' for flex objects which I can use here.
Please help.
Thanks in advance.
If you mean if an Object has no properties:
var isEmpty:Boolean = true;
for (var n in obj) { isEmpty = false; break; }
This is some serious hack but you can use:
Object.prototype.isEmpty = function():Boolean {
for(var i in this)
if(i != "isEmpty")
return false
return true
}
var p = {};
trace(p.isEmpty()); // true
var p2 = {a:1}
trace(p2.isEmpty()); // false
You can also try:
ObjectUtil.getClassInfo(obj).properties.length > 0
The good thing about it is that getClassInfo gives you much more info about the object, eg. you get the names of all the properties in the object, which might come in handy.
If object containes some 'text' but as3 doesn't recognize it as a String, convert it to string and check if it's empty.
var checkObject:String = myObject;
if(checkObject == '')
{
trace('object is empty');
}
Depends on what your object is, or rather what you expect it to have. For example if your object is supposed to contain some property called name that you are looking for, you might do
if(objSomeItem == null || objSomeItem.name == null || objSomeItem.name.length == 0)
{
trace("object is empty");
}
or if your object is actually supposed to be something else, like an array you could do
var arySomeItems = objSomeItem as Array;
if(objSomeItem == null || arySomeItems == null || arySomeItems.length == 0)
{
trace("object is empty");
}
You could also use other ways through reflection, such as ObjectUtil.getClassInfo, then enumerate through the properties to check for set values.... this class help:
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
public class ReflectionUtils
{
/** Returns an Array of All Properties of the supplied object */
public static function GetVariableNames(objItem:Object):Array
{
var xmlPropsList:XMLList = describeType(objItem)..variable;
var aryVariables:Array = new Array();
if (xmlPropsList != null)
{
for (var i:int; i < xmlPropsList.length(); i++)
{
aryVariables.push(xmlPropsList[i].#name);
}
}
return aryVariables;
}
/** Returns the Strongly Typed class of the specified library item */
public static function GetClassByName($sLinkageName:String):Class
{
var tObject:Class = getDefinitionByName($sLinkageName) as Class;
return tObject;
}
/** Constructs an instance of the speicified library item */
public static function ConstructClassByName($sLinkageName:String):Object
{
var tObject:Class = GetClassByName($sLinkageName);
//trace("Found Class: " + tMCDefinition);
var objItem:* = new tObject();
return objItem;
}
public static function DumpObject(sItemName:String, objItem:Object):void
{
trace("*********** Object Dump: " + sItemName + " ***************");
for (var sKey:String in objItem)
{
trace(" " + sKey +": " + objItem[sKey]);
}
}
//}
}
Another thing to note is you can use a simple for loop to check through an objects properties, thats what this dumpobject function is doing.
You can directly check it as follow,
var obj:Object = new Object();
if(obj == null)
{
//Do something
}
I stole this from a similar question relating to JS. It requires FP 11+ or a JSON.as library.
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
can use use the hasProperty method to check for length
var i:int = myObject.hasProperty("length") ? myObject.length: 0;

Resources